laravel-actions icon indicating copy to clipboard operation
laravel-actions copied to clipboard

Using validation and authorization without running as a controller

Open nathan-io opened this issue 2 years ago • 1 comments

I read the "Add validation to your controllers" doc.

We have a Livewire component which provides UI for CRUD of a resource (Phone, for example).

While Livewire provides validate() as a way of validating the request against the defined rules, I'm wondering if we should forgo that and instead centralize validation rules (and authorization, for that matter) in the Action class.

Here's a current work in progress implementation which is using the Validator facade for now:

CreatePhoneAction class:

    public function handle($data, $userId) {
        $validator = Validator::make($data, [
            // our rules
        ]);

        if ($validator->fails()) {
            return [
                'success' => false,
                'data' => $validator->errors()->all(),
            ];
        }

        $phone = Phone::create($validator->validated());

        return [
            'success' => true,
            'data' => $phone,
        ];
     }

In the Livewire component class, our method which handles creation:

    public function create()
    {
        $data = $this->getFormData();

        $response = CreatePhoneAction::run(data: $data, userId: Auth::id());

        if($response['success']) {
            $this->emit('modal-close', 'phone_modal');
            $this->alert('success', 'Phone saved successfully!');
            $this->emit('refreshParentTable');
            return;
        } else{
            foreach($response['data'] as $i => $errorItem){
                $this->addError('error-' . $i, $errorItem);
            }
        }

    }

As you can see, we're currently not leveraging the rules() or authorize() methods provided by ActionRequest.

While this action isn't being run as a controller and there's no route that it's registered to, it could still receive a Request from Livewire, which we can validate and authorize.

I believe this question only arises in situations where we're using a Livewire component to handle CRUD rather than traditional resource routes.

Hope this makes sense. I'm admittedly still learning about the package and the action pattern. It's also possible that I'm thinking about this in the wrong way.

I appreciate any suggestions or feedback.

nathan-io avatar Mar 02 '22 23:03 nathan-io

If I understand you well, I think you can use $action->fillFromRequest($request) in your handle method, for example:

  public function handle(array $attributes = [])
   {
       $this->fill($attributes);
       $validatedData = $this->validateAttributes();
       
       $phone = Phone::create($validator->validated());

       return [
           'success' => true,
           'data' => $phone,
       ];
   }

Don't forget to use WithAttributes trait for this to work.

onemoreahmad avatar Aug 23 '22 08:08 onemoreahmad