Search code examples
laravelvalidationlaravel-5.7customvalidator

Adding validation rule only if all other rules pass, or stop validating entire set of attributes on the first error in Laravel 5.7


I want to allow a user to create a folder on the local storage disk. So the form that is sent to the server quite is simple and has three attributes:

  1. new-folder-name - that is the name of the folder to be created,
  2. relative-path - a path to the directory inside which the new directory should be created relative to an asset root directory, and
  3. asset_id - the id of an asset, I need this id to get the asset's root directory.

The thing is when I validate these attributes I need to also check if the folder the user is going to create already exists. For this purpose I made a rule called FolderExists. So, before I run FolderExists, I have to be sure all other rules have passed successfully because my custom rule should accept relative-path and asset_id to be able to build the path to check against.

Here is my rules() function, I'm doing validation in custom form request:

public function rules()
{
    return [
        'asset_id' => ['bail', 'required', 'exists:assets,id'],
        'relative-path' => ['bail', 'required', 'string'],
        'new-folder-name' => ['bail', 'required', 'string', 'min:3', new FolderName, new FolderExists($this->input('asset_id'), $this->input('relative-path')]
    ];
}

So my question is:

Is it possible to add FolderExists only if all other validation rules pass?

Or maybe it's possible to stop entire validation when the validator encounters first error?

Both options should be fine here.

Thank you!


Solution

  • I have finally found the solution myself. Here is what I ended up with.

    To achieve the desired result I created another validator in withValidator() method of my custom form request, this second validator will handle only the FolderExists rule and only if the previous validation fails.

    public function rules()
        {
            return [
                'asset-id' => ['bail', 'required', 'integer', 'exists:assets,id'],
                'relative-path' => ['bail', 'required', 'string'],
                'new-folder-name' => ['bail', 'required', 'string', 'min:3', 'max:150', new FolderName]
            ];
        }
    
    public function withValidator($validator)
        {
            if (!$validator->fails())
            {
                $v = Validator::make($this->input(),[
                    'new-folder-name' => [new FolderExists($this->input('asset-id'), $this->input('relative-path'))]
                ]);
                $v->validate();
            }
        }
    

    If our main validator passes, we make another validator and pass only FolderExists rule with its arguments, that have already been validated, and call validate() method. That's it.