Search code examples
phplaravelvalidationrequest

Laravel 11 validation requiring a single item in an array has to be one of the following


I am using form request validation and allow for vehicles to be created in the form. Each vehicle has a ref which can be A, B, C, or D. However, in each form request there must always be a single ref: "A". There can be any amount of the others.

I am not in control of the form. The requests come through an API.

My rules array currently contains:

'form.vehicles' => 'required',
'form.vehicles.*.ref' => 'required|in:A,B,C,D

Currently I am using the following code:

if (! in_array('A', $this->input('form.vehicles.*.ref'))) {
  throw new HttpResponseException(response()->json(['MessageString' => 'Vehicle ref A is required'], 422));

This however means the messageBag is unable to be sent in the response for other validation issues.


Solution

  • I used Tim Lewis's suggestion of creating a custom rule implementing ValidationRule:

    namespace App\Rules;
    
    use Illuminate\Contracts\Validation\ValidationRule;
    
    class VehicleA implements ValidationRule
    {
        /**
         * Run the validation rule.
         *
         * @param  \Closure(string): \Illuminate\Translation\PotentiallyTranslatedString  $fail
         */
        public function validate(string $attribute, mixed $value, Closure $fail): void
        {
            $requiredVehicle = collect($value)->first(function ($vehicle) { 
                return $vehicle['ref'] === 'A';
            });  
    
            if ($requiredVehicle === null) { 
                $fail('Vehicle A is required'); 
            }
        }
    

    Inside my form request:

    'form.vehicles' => [
        'required',
        new VehicleA,
    ],