Laravel 9动态创建自定义请求时验证提前触发问题求助
动态创建Laravel自定义请求时提前触发验证的解决方案
在Laravel 9中动态创建StoreContactRequest实例时,验证会在实例化阶段立即触发,导致无法先添加请求数据,期望验证逻辑在ContactController::store()方法内执行。
ProjectController 的 store 方法
// 创建项目时同时保存客户联系人 public function store(StoreProjectRequest $request) { //dd($request->only('contact')['contact']); $storeContactReq = app()->make(\App\Http\Requests\StoreContactRequest::class); // 验证在此处触发,无法执行后续代码 $storeContactReq->request->add($request->only('contact')['contact']); $storeContactReq->setMethod('POST'); $cc = new ContactController(); $con = $cc->store($storeContactReq); dd($con); //.... }
StoreContactRequest 代码
class StoreContactRequest extends FormRequest { public function authorize() { return true; } public function rules() { return [ "lastname" => 'required', "firstname" => 'required', "email" => 'required|email', "phone" => 'required', "street" => 'required', "house" => 'required', "postcode" => 'required', "city" => 'required', ]; } public function messages() { return [ 'firstname.required' => 'Vorname ist leer', 'lastname.required' => 'Nachname ist leer', 'street.required' => 'Straße ist leer', 'house.required' => 'Hausnummer ist leer', 'postcode.required' => 'Postleitzahl ist leer', 'city.required' => 'Ort ist leer', 'phone.required' => 'Telefon ist leer', 'email.required' => 'Email ist leer', 'email.email' => 'Email ist keine korrekte Mailadresse' ]; } public function failedValidation(Validator $validator) { dd($validator->errors()); } }
错误信息
Illuminate\Support\MessageBag^ {#1359 // app/Http/Requests/StoreContactRequest.php:56 #messages: array:8 [ "lastname" => array:1 [ 0 => "Nachname ist leer" ] "firstname" => array:1 [ 0 => "Vorname ist leer" ] "email" => array:1 [ 0 => "Email ist leer" ] "phone" => array:1 [ 0 => "Telefon ist leer" ] "street" => array:1 [ 0 => "Straße ist leer" ] "house" => array:1 [ 0 => "Hausnummer ist leer" ] "postcode" => array:1 [ 0 => "Postleitzahl ist leer" ] "city" => array:1 [ 0 => "Ort ist leer" ] ] #format: ":message" }
解决方案
Laravel的FormRequest通过容器实例化时会自动触发验证流程,以下是三种可行的解决方式:
方法一:手动构建请求实例并绑定到容器
绕过容器自动解析的验证逻辑,手动创建请求实例并注入数据,再绑定到容器供控制器使用:
public function store(StoreProjectRequest $request) { $contactData = $request->input('contact'); // 手动创建请求实例 $storeContactReq = new \App\Http\Requests\StoreContactRequest(); // 注入联系人数据 $storeContactReq->merge($contactData); $storeContactReq->setMethod('POST'); // 将请求实例绑定到容器,确保控制器方法能正确解析 app()->instance(\App\Http\Requests\StoreContactRequest::class, $storeContactReq); $cc = app(\App\Http\Controllers\ContactController::class); $con = $cc->store($storeContactReq); dd($con); // ...后续逻辑 }
方法二:直接使用Validator手动验证
跳过FormRequest实例化,复用其规则和消息手动完成验证,再调用控制器逻辑:
public function store(StoreProjectRequest $request) { $contactData = $request->input('contact'); // 复用StoreContactRequest的规则与消息创建验证器 $validator = \Illuminate\Support\Facades\Validator::make( $contactData, (new \App\Http\Requests\StoreContactRequest())->rules(), (new \App\Http\Requests\StoreContactRequest())->messages() ); // 验证失败时抛出标准异常,与FormRequest行为一致 if ($validator->fails()) { throw new \Illuminate\Validation\ValidationException($validator); } // 创建模拟请求传递给控制器 $fakeRequest = \Illuminate\Http\Request::create('/', 'POST', $contactData); $cc = new \App\Http\Controllers\ContactController(); $con = $cc->store($fakeRequest); dd($con); // ...后续逻辑 }
方法三:修改FormRequest控制验证时机(不推荐)
通过重写validateResolved方法,添加开关控制自动验证的触发时机:
class StoreContactRequest extends FormRequest { protected $autoValidate = true; public function setAutoValidate(bool $autoValidate) { $this->autoValidate = $autoValidate; return $this; } public function validateResolved() { if ($this->autoValidate) { parent::validateResolved(); } } // ...原有代码不变 }
在控制器中使用:
public function store(StoreProjectRequest $request) { // 实例化时关闭自动验证 $storeContactReq = app()->make(\App\Http\Requests\StoreContactRequest::class)->setAutoValidate(false); $storeContactReq->merge($request->input('contact')); $storeContactReq->setMethod('POST'); // 手动开启验证(或由ContactController的store方法自动触发) $storeContactReq->setAutoValidate(true); $cc = new \App\Http\Controllers\ContactController(); $con = $cc->store($storeContactReq); dd($con); }
内容的提问来源于stack exchange,提问作者FFG IT
相关产品推荐
相关产品推荐

