Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

PierceMcGeough's avatar

Validation custom query

I am having trouble getting the following to do what I need.

I have the following validation rules

return [
    'facility_booked' => 'required|array',
    'facility_booked.*.facility_id' => 'required|exists:facilities,id',
    'facility_booked.*.start_time' => [
        'required',
        'date_format:Y-m-d H:i',
        app()->get(FacilityStartTimeExists::class)
    ],
    'facility_booked.*.checked_in' => 'boolean',
    'facility_booked.*.rate.id' => [
        'exists:availability_rates,id',
        new AvailabilityRateBookableByUser()
    ],
];

The models are set up like this. FacilityBooked hasOne Facility and then Facility will have a category_id.

When passing through a payload like the below I want to add a rule that checks the category_id of each facility is the same. So we can have different facility_ids but if we do then those facilities must have the same category_id

{
  "facility_booked": [
    {
      "facility_id": 1,
      "start_time": "2024-03-11 07:00",
      ...
    },
    {
      "facility_id": 5,
      "start_time": "2024-03-11 07:00",
      ...
    }
  ],
  ...,
  ...
}

Is it possible to reach into the model children at this stage? I am thinking I need to reach the facility rather than the facility_id here and do some custom query to check for same or different category_id

 'facility_booked.*.facility' => 'required|customCategoryIdQuery,
0 likes
2 replies
PierceMcGeough's avatar

So I ended up needing a different approach.

I created a new rule FacilitiesBookedSameFacilityCategory which would do the check. At first I didn't realise the validation would loop over each iteration of the facility id based on $attribute and $value but I needed access to all the posted data at once so I used the DataAwareRule

$facilityIds = data_get($this->data, 'facility_booked.*.facility_id');

$facilityCategoryCount = Facility::whereIn('id', $facilityIds)->get()
    ->unique('category_id')
    ->count();

if ($facilityCategoryCount > 1) {
    $fail('Please only book facilities with the same category type');
}	

Another issue was that I originally had the rule set on the facility_booked facility_id which left it running the rule check multiple times even though once was enough

'facility_booked.*.facility_id' => [
    'required',
    'exists:facilities,id',
    new FacilitiesBookedSameFacilityCategory
],

A simple fix here was to move this rule check to another rule that would only be called once

'facility_booked' => [
    'required',
    'array',
    new FacilitiesBookedSameFacilityCategory
],
1 like

Please or to participate in this conversation.