Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create a dependent validation rule in Nova?

I have fields defined as the following for a resource in Nova:

Select::make('Type')
    ->options([
        'video' => 'Video',
        'download' => 'Download',
        ])
    ->rules('required'),    

File::make('File', 'file_name')
    ->disk('local')
    ->path('/files')

I am trying to setup different validation rules for the File field depending on the value of the type field. For example where the type is download accept document mimes and a max size of 1mb, whilst if set as video accept video file mimes and max size of 30mb.

I haven't really got anywhere with trying to achieve this.

I've looked through the docs and neither validation rule objects or custom closure rules will help me as I wont be able to access the value of the type field from them.

Similarly, I thought of extending the NovaRequest object as one might do with a FormRequest, but this wouldn't do the front-end validation that Nova applies.

Is there any way to achieve this that I'm missing?

like image 533
Rory Avatar asked Sep 06 '25 01:09

Rory


1 Answers

I now have this working through the tutorial provided here from John Beales who is similarly complaining that Nova doesn't pick up on Laravel Form Requests automatically.

1: Create a Request for the Nova Resource that extends FormRequest:

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;


class StoreResourceRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        // Users authorized to make the request are:
        // - users updating themselves.
        // - staff
        // - guests creating a new user.


        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {

        $rules = self::ruleGetter($this);


        if(empty($this->user())) {
            $rules = array_merge_recursive($rules, self::creationRuleGetter($this));
        } else {
            $rules = array_merge_recursive($rules, self::updateRuleGetter($this));
        }

        return $rules;
    }

    public static function ruleGetter( $request, $rule = null ) {

        $rules = [
            'type' =>  ['required',Rule::in(['video', 'download'])],
        ];

        if($request['type'] == 'download'){
            $rules['file_name'] = ['required','mimes:jpeg,png,jpg,doc,docx,pdf','max:1000'];
        } 

        if($request['type'] == 'video'){
            $rules['file_name'] = ['required','mimes:mp4','max:50000'];
        }

        if(!empty($rule)) {
            if(isset($rules[$rule])) {
                return $rules[$rule];
            }
            return '';
        }
        return $rules;
    }

    public static function creationRuleGetter( $request, $rule = null ) {
        $rules = [

        ];


        if(!empty($rule)) {
            if(isset($rules[$rule])) {
                return $rules[$rule];
            }
            return '';
        }
        return $rules;

    }

    public static function updateRuleGetter( $request, $rule = null ) {


        $rules = [

        ];

        if(!empty($rule)) {
            if(isset($rules[$rule])) {
                return $rules[$rule];
            }
            return '';
        }
        return $rules;
    }

}

2: Update Nova Resource to load these rules:

namespace App\Nova;

use App\Http\Requests\StoreResourceRequest;

//...

public function fields(Request $request)
{
    return [
        //...

        Select::make('Type')
        ->options([
            'video' => 'Video',
            'download' => 'Download',
        ])
        ->rules(StoreResourceRequest::ruleGetter($request, 'type')),

        File::make('File', 'file_name')
        ->rules(StoreResourceRequest::ruleGetter($request, 'file_name'))

    ];
}

The above works for both types of validation and stores the correct value in the database. Nova can interact with the file normally.

It's just a pity this isn't built in to Nova and the validation logic has to be duplicated.

like image 157
Rory Avatar answered Sep 09 '25 01:09

Rory