Home > Software design >  What is better way to pass parameters into service method?
What is better way to pass parameters into service method?

Time:11-07

Here is a service that implements interface

interface Rating
{
 
    function create(User $user, User $rateduser, Rating $rating, Order $order);

}

The controller acceepts the request object:

{"rating": [{"rateid": 1, "rate": 4}], "userid": 1}

When I try to pass whole data into service:

public function store(RateRequest $request)
{
    $rating = RatingData::from(
        [
            'rateid' => $request->get('rating.rateid'),
            'rate' => $request->get('rating.rate'),
        ]
    );

    $user = Auth()::user();
    $rateduser = User::find($request->id);
    $order = new Order;

    $this->rating->create($user, $rateduser, $rating, $order);
}

How is better pass parametres into funciton using ideniticators $userid, $rateUserId, $orderId or concrete models? Or left it such as now?

interface Rating
{
 
    function create(int $userid, int $rateUserId, Rating $rating, int $order);

}

The controller looks dirty in my case.

Another problem what if tomorrow my model will be changed from eloquent to another? Then I have to change service methods

CodePudding user response:

I can suggest the following approach if you want to keep your controllers clean. (I do not claim that it is the only correct one)

Dto:

class RatingDto extends DataTransferObject
{
    public int $rateId;

    public int $rate;
}

class CreateRatingDto extends DataTransferObject
{
    public int $userId;

    public int $rateUserId;

    /** @var RatingDto[] */
    #[CastWith(ArrayCaster::class, itemType: RatingDto::class)]
    public array $ratings;
}

Request:

class CreateRatingRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'ratedUserId' => 'required|integer|exists:users,id',
            'ratings' => 'required|array',
            'ratings.*.rateId' => 'required|integer',
            'ratings.*.rate' => 'required|integer|min:1|max:5',
        ];
    }

    public function getDto(): CreateRatingDto
    {
        return new CreateRatingDto([
            'userId' => Auth::user()->id,
            'ratedUserId' => $this->input('ratedUserId'),
            'ratings' => $this->input('ratings'),
        ]);
    }
}

Interface:

interface RatingServiceInterfate
{
    public function create(CreateRatingDto $dto): RatingModel;
}

Controller:

class RatingController extends Controller
{
    private RatingServiceInterfate $ratingService;

    public function __construct(RatingServiceInterfate $ratingService)
    {
        $this->ratingService = $ratingService;
    }

    public function store(CreateRatingRequest $request): JsonResource
    {
        $rating = $this->ratingService->create($request->getDto());

        return new RatingResource($rating);
    }
}

Also, this implementation does not bind your service to models. At any time you can write a new interface implementation and substitute it through ServiceProvider. (if for example in another part of the application you need to save data to another database not compatible with eloquent)

  • Related