no0by5
no0by5

Reputation: 632

Best way to validate Laravel Requests

In my Resource Controller I have a store and an update function with nearly the same validation rules. Because my validation is a bit more complicated I created a Request for this.

But because the validation rules differ a bit, I have to create two Requests:

But so I have nearly the same array in two different places and if I decide to change it, I have to edit two different files. Is there a better way to do this?

I thought about creating an extra Request class which has an array with the common rules and the classes for the store and update Request inherit from this class and use the array from the base class to put together the validation rules.

But to add an extra class and inherit from it seems a little too much for me, just because one or to rules are different.

Another way I thought about was to only check the common rules in the Request class and add an extra validation in the store and update functions, but then the validation would be done in two different places, which would make the project more confusing.

I'm using Laravel version 5.8

Upvotes: 4

Views: 9682

Answers (4)

saber tabatabaee yazdi
saber tabatabaee yazdi

Reputation: 4959

$validated = $request->validated();

use this:

public function createAccount(RegisterRequest $request)
{
    $attr = $request->validated();

instead of :

public function createAccount(Request $request)
{
    $attr = $request->validate([
        'name' => 'required|string|max:255',
        'email' => 'required|string|email|unique:users,email',
        'password' => 'required|string|min:6|confirmed'
    ]);

php artisan make:request RegisterRequest

public function rules()
{
    return [
        'name' => 'required|string|max:255',
        'email' => 'required|string|email|unique:users,email',
        'password' => 'required|string|min:6|confirmed'
    ];
}

Upvotes: 0

apokryfos
apokryfos

Reputation: 40653

I do suggest inheritance:

abstract class BaseRequest extends FormRequest {

        public function rules() {
              return [ /* common rules */ ]; 
        }
}

class StoreRequest extends BaseRequest {

       public function rules() {
           return array_merge(parent::rules(), [
               /* extra rules including overrides
           ]);
       }
}

You can do the same for the update request as well. This creates a central place to manage the commonalities in the request.

This being said without actual code we can't really know what's most appropriate for your case.

Upvotes: 4

ceejayoz
ceejayoz

Reputation: 179994

You can check for the presence of something in the request that indicates an update. For example:

public function rules() {
    $rules = [];

    // these rules apply to both
    $rules['title'] = ['required'];

    if($this->input('id')) {
        // these rules only apply to updates
        $rules['something_specific_to_updates'] = ['foo'];
    } else {
        // these rules only apply to new records
        $rules['something_specific_to_new_records'] = ['bar'];
    }

    return $rules;
}

You can also look at $this->route('id') to look at the value of a route parameter rather than one in the form's $this->input POST data.

Upvotes: 1

Kenny Horna
Kenny Horna

Reputation: 14241

As @apokryfos says, its hard to tell without context but if you doesn't want to use inheritance, you could validate the request method inside the request class to add/remove elements from the validation array:

/** YourCustomFormRequest.php */

    //

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
       $rules = ['here', 'goes', 'your', 'common', 'rules'];

       if ($this->isMethod('post'))
       {
           array_merge($rules, ['a', 'specific', 'rule']);           
       }

       if ($this->isMethod('put')) // or 'patch'
       {
           array_merge($rules, ['another', 'specific', 'rule']);           
       }


        return $rules;
    }

    //

The logic behing this is, when you create an object, you should make a POST request, but when updating you use PUT/PATCH instead, so we are just getting the used method to add/remove conditions from the validation array.

Haven't test it yet, but this should work.


PS: In order to have a better code, you should consider decoupling the code and create specific classes.

Upvotes: 3

Related Questions