Laravel验证嵌套JSON时如何向自定义规则传入当前索引的对象
解决方案
你可以通过解析当前验证属性的路径获取数组索引,再拿到同索引下的完整对象,以下是两种常用实现方式:
方案1:修改现有自定义规则类(推荐,适合复用逻辑)
直接修改你的SeatIsAvailable规则类,在passes方法中解析属性路径获取当前索引,再从请求中获取对应完整座位数据:
<?php namespace App\Rules; use Illuminate\Contracts\Validation\Rule; class SeatIsAvailable implements Rule { public function passes($attribute, $value) { // 拆分属性路径获取当前数组索引,对应seats.*.seat_no里的*位置 $index = explode('.', $attribute)[1]; // 获取当前索引对应的完整座位对象 $seat = request()->input("seats.{$index}"); $scheduleId = $seat['schedule_id'] ?? null; $date = $seat['date'] ?? null; // 基础参数非空判断(调整规则顺序后可省略) if (!$scheduleId || !$date) { return false; } // 这里写你的实际校验逻辑,比如查询座位是否在指定排班、日期下可用 return !\App\Models\Seat::where('schedule_id', $scheduleId) ->where('date', $date) ->where('seat_no', $value) ->exists(); } public function message() { return '该座位在指定日期和排班下已被占用'; } }
这个方案不需要修改你现有CheckoutRequest的调用逻辑,仅建议调整规则顺序,保证schedule_id和date的基础校验在seat_no之前,避免参数缺失问题:
public function rules() { return [ "company" => "required", "seats" => "required|array", "seats.*.schedule_id" => "required|numeric", "seats.*.date" => "required|date", "seats.*.seat_no" => ['required', new SeatIsAvailable()], ]; }
方案2:使用闭包验证(适合逻辑无需复用的场景)
如果校验逻辑不需要在其他地方复用,可以直接在表单请求规则中用闭包实现,无需额外创建规则类:
public function rules() { return [ "company" => "required", "seats" => "required|array", "seats.*.schedule_id" => "required|numeric", "seats.*.date" => "required|date", "seats.*.seat_no" => [ 'required', function ($attribute, $value, $fail) { $index = explode('.', $attribute)[1]; $seat = $this->input("seats.{$index}"); if (\App\Models\Seat::where('schedule_id', $seat['schedule_id']) ->where('date', $seat['date']) ->where('seat_no', $value) ->exists()) { $fail("座位{$value}在指定日期已被占用"); } } ], ]; }
内容的提问来源于stack exchange,提问作者user3718908x100
相关产品推荐
相关产品推荐

