uverest's avatar

How to (correctly) use custom FormRequest rules calling it inside a controller method?

I have this custom request Class.

class EmployeeRequest extends FormRequest { public function authorize(): bool { return true; }

public function rules(): array
{
    $employeeId = $this->route('employee');

    return [
        'company_id' => 'required|exists:companies,id',
        'position_id' => 'required|exists:employee_positions,id',
        'name' => 'required|string|max:191',
        'email' => [
            'nullable',
            'email',
            'max:254',
            Rule::unique('employees')->ignore($employeeId),
        ],
       ...
    ];
}

}

But in the Controller, I receive (sometimes) this Entity inside a key of a JSON object. Example: { param1: 'test', param2: 'test', employee: { company_id: 1, rest_of_employee_data... }

So, I can't just have something like this: public function store(ScheduleRequest $scheduleRequest, EmployeeRequest $employeeRequest){ ... }

Because Laravel will do the validation on a full request level.

How do I make something like...? public function store(ScheduleRequest $scheduleRequest) { if($scheduleRequest->input('employee')){ THEN APPLY HERE THE EMPLOYEE REQUEST RULES } }

Sorry by my bad english. Best regards

0 likes
1 reply
vincent15000's avatar

You can do exactly like you suggested.

public function store(ScheduleRequest $scheduleRequest)
{
	if ($scheduleRequest->input('employee')) {
		// THEN APPLY HERE THE EMPLOYEE REQUEST RULES
	}
}

So you receive some data in the request and according to these data, you need to apply one or another rule ?

You can also apply conditional rules directly inside the form request. Here is an example how I have done in one of my projects.

I don't have the same fields according to the datasource.

public function rules(): array
{
    $rules = [
        'datasource' => 'required|in:'.implode(',',array_column(DatasourceEnum::cases(), 'value')),
        'datasource_credentials' => 'required|array',
    ];

    foreach (DatasourceEnum::cases() as $datasource) {
        $fields = $datasource->credentialsFields();
        
        if ($fields) {
            foreach ($fields as $field) {
                $rules['datasource_credentials.'.$field] = 'required_if:datasource,'.$datasource->value;
            }
        }
    }

    return $rules;
}

You can also check one of the fields to apply custom rules according to the type (employee, admin, ...).

public function rules(): array
{
    $rules = [
        'param1' => 'required|string',
        'param2' => 'required|string',
        'employee' => 'nullable|array',
		'employee.name' => 'required_with:employee',
		...
    ];

    return $rules;
}

Please or to participate in this conversation.