TransWikia.com

Return payload in service layer

Code Review Asked on October 27, 2021

In my project I am using the ADR architecture, a branch of MVC.

In my actions (Controllers) I handle only data that comes from the request.

When there is a business rule that defines which status code I return, I do this treatment in my service.

Imagine this scenario:

When editing a user, I check if the user’s email already exists, if it exists, I return an error informed to your message. This treatment is done in the service, and in these cases I get the error in it.

I would like to hear from you about my approach to, in some cases, the service layer returning the payload.

Action:

class CreateUserAction extends Action
{
    private $userService;


    /**
     * @param UserService $userService
     */
    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }

    public function handle(Request $request) : JsonResponse
    {
        $data = $request->getData();

        $payload = $this->userService->create($data, $user);

        return response()->json($payload->body, $payload->statusCode);
    }
}

Service:

class UserService extends BaseService
{
    private $userRepository;

    public function __construct(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function create(array $data) : object
    {
        if ($this->userRepository->findByEmail($data['email'])) {
            $this->setPayloadError(
                __('messages.user.contributor_email_already_exists'),
                Response::HTTP_BAD_REQUEST
            );
            return $this->getPayload();
        }
        
        $userCreated = $this->userRepository->create($data);

        $this->setPayload($userCreated, Response::HTTP_CREATED);
        return $this->getPayload();

    }
}
```

One Answer

In my actions (Controllers) I handle only data that comes from the request.

If above is the case you might be better off handling validation before calling service class. In other words, prepare data into a format that business service classes can understand. Same applies about a decision on which HTTP Code to return.

I am not sure why you have single responsibility controllers, a number of files would bloat very quickly in a larger application.

Controller:

class CreateUserAction extends Action
{ 
    public function handle(UserCreateRequest $request): JsonResponse
    {
        return (new UserService)->create($request->validated(), $user);

        // OR
        $user = (new UserService)->create($request->validated(), $user);

        return response($user, Response::HTTP_CREATED);
    }
}

I am not sure why you are using repository unless you are doing complex DB operation. Service should have all the business logic. This way service layer/business logic can be easier extracted and reused in other applications thanks to less dependencies.

use App/Models/User;

class UserService extends BaseService
{ 
    public function create(array $data): User
    { 
        return (new userRepository)->create($data); 

    }
}

Answered by user3402600 on October 27, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP