Laravel控制器中如何避免输入验证时的重复数据库查询?
解决Laravel验证器重复查询数据库的问题
你的代码里,exists:users,id规则会先执行一次count(*)查询验证用户存在,之后User::find()又查一次获取用户数据,前后两次数据库请求完全没必要。下面是几种既能保留Laravel验证器便利性,又能只查一次数据库的方案:
方案一:用验证闭包查询并缓存用户实例
把exists规则换成自定义闭包,在验证阶段完成用户查询,还能把实例存到请求里,后面直接用:
function myRequest(Request $request) { $validator = Validator::make($request->all(), [ 'user_id' => [ 'required', 'integer', 'min:1', function ($attribute, $value, $fail) use ($request) { // 只查一次数据库 $user = User::find($value); if (!$user) { $fail('指定的用户不存在'); } // 把用户实例存到request里,后续直接调用 $request->attributes->set('user', $user); } ], // 其他字段的验证规则 ]); if ($validator->fails()) { // 这里写错误处理逻辑,比如返回带错误信息的页面 return redirect()->back()->withErrors($validator); } // 直接从request拿用户实例,不用再查库 $user = $request->get('user'); // 接下来处理业务逻辑 }
方案二:先查用户,再补验证错误
先执行一次用户查询,然后用验证器处理其他字段规则,要是用户不存在,手动给验证器加错误信息:
function myRequest(Request $request) { // 单次查询用户 $user = User::find($request->input('user_id')); $validator = Validator::make($request->all(), [ 'user_id' => 'required|integer|min:1', // 其他字段的验证规则 ]); // 用户不存在的话,手动添加验证错误 if (!$user) { $validator->errors()->add('user_id', '指定的用户不存在'); } if ($validator->fails()) { // 错误处理逻辑 return redirect()->back()->withErrors($validator); } // 直接用已经查到的$user // 后续业务处理 }
方案三:用findOrFail结合异常处理(适合简单场景)
如果只需要验证用户存在并获取实例,可以去掉exists规则,用findOrFail——它会在用户不存在时抛出异常,Laravel的全局异常处理器会自动处理返回错误,全程只查一次库:
function myRequest(Request $request) { $validator = Validator::make($request->all(), [ 'user_id' => 'required|integer|min:1', // 其他字段的验证规则 ]); if ($validator->fails()) { // 错误处理逻辑 return redirect()->back()->withErrors($validator); } // 单次查询,不存在就抛ModelNotFoundException $user = User::findOrFail($request->input('user_id')); // 后续业务处理 }
提示:默认Laravel会给
ModelNotFoundException返回404页面,如果需要自定义响应(比如JSON错误),可以在app/Exceptions/Handler.php里修改对应的异常处理逻辑。
内容的提问来源于stack exchange,提问作者Dimitrios Desyllas
相关产品推荐
相关产品推荐

