Laravel中如何让Car类接收CarRequest替代通用VehicleRequest实现额外校验
实现方案
Laravel FormRequest 场景适配
你可以通过继承父类请求+手动实例化子类请求触发校验的方式实现,步骤如下:
- 定义子类请求继承
VehicleRequest,补充额外校验规则
class CarRequest extends VehicleRequest { // 合并父类校验规则,补充当前类专属校验 public function rules() { return array_merge(parent::rules(), [ 'wheels' => 'required|integer|in:4', 'brand' => 'required|string|in:bmw,audi,benz' ]); } }
摩托类请求MotorCycleRequest按相同逻辑定义即可。
2. 改造init方法,根据类型实例化对应子类请求,校验完成后传入对应类构造函数
public function init(VehicleRequest $request){ // 修正原代码的语法错误:判断逻辑需将比较运算符放在input方法外 if($request->input('type') == 'car'){ // 从已有请求实例创建CarRequest实例,复用原有请求数据 $carRequest = CarRequest::createFrom($request); // 手动触发校验,不通过会自动抛出和框架默认行为一致的验证异常 $carRequest->validateResolved(); $vehicle = new Car($carRequest); } else { $motorRequest = MotorCycleRequest::createFrom($request); $motorRequest->validateResolved(); $vehicle = new MotorCycle($motorRequest); } }
- 改造
Car类构造函数的参数类型提示为CarRequest即可
class Car{ public function __construct(CarRequest $request){ // 此处拿到的$request已经过父类+子类两层校验,可直接使用 } }
通用PHP类场景适配
如果不是Laravel框架,可通过子类请求接收父类请求实例、复制参数后自行校验的方式实现:
- 定义子类请求
class CarRequest extends VehicleRequest { public function __construct(VehicleRequest $request) { // 复制父类请求的所有参数 parent::__construct($request->all()); // 执行专属校验逻辑 $this->validateExtra(); } protected function validateExtra() { if ($this->input('wheels') !== 4) { throw new \InvalidArgumentException('汽车车轮数必须为4'); } if (!in_array($this->input('brand'), ['bmw', 'audi', 'benz'])) { throw new \InvalidArgumentException('品牌不在允许范围内'); } } }
- 改造
init方法
public function init(VehicleRequest $request){ if($request->input('type') == 'car'){ $vehicle = new Car(new CarRequest($request)); } else { $vehicle = new MotorCycle(new MotorCycleRequest($request)); } }
内容的提问来源于stack exchange,提问作者gasgen
相关产品推荐
相关产品推荐

