Laravel下REST规范PUT方法实现upsert的模型绑定问题咨询
解决方案
你需要调整绑定逻辑和控制器参数定义即可实现需求,不需要修改其他路由的默认绑定规则:
1. 修正RouteServiceProvider中的绑定逻辑
你之前的绑定逻辑错误地在非PUT请求时返回了字符串ID,不符合模型绑定的返回要求,才会触发404异常。调整为仅在update路由下允许返回空,其他路由走默认的不存在即404逻辑:
// RouteServiceProvider boot方法内 Route::bind('user', function($userId, $route) { $userQuery = User::where(fn($query) => $query->where('id', $userId)->orWhere('email', $userId)); // 只有update路由允许不存在时返回null if ($route->getActionMethod() === 'update') { return $userQuery->first(); } // 其他路由找不到直接返回404 return $userQuery->firstOrFail(); });
2. 调整控制器update方法的参数定义
把模型参数改为可空类型,同时补全PATCH请求不存在资源的404判断:
// 加?标记参数可为null public function update(Request $request, ?User $user) { $input = $request->all(); $method = $request->method(); if($method === 'PUT') $request->validate($this->rules); // PATCH仅允许更新已存在资源,不存在直接返回404 if ($method === 'PATCH' && !$user) { abort(404); } $update = [ 'PUT' => fn() => $user ? $user->update($input) : User::create($input), 'PATCH' => function() use($user, $input){ foreach ($input as $key => $val){ $user->$key = (!empty($val)) ? $val : $user->$key; } $user->save(); return $user; } ]; return response()->json($update[$method]()); }
关键说明
- Laravel的隐式模型绑定如果参数加了可空标记
?,当绑定返回null时不会抛出404异常,会直接把null传入控制器 - 路由绑定的第二个参数是当前路由实例,可以通过
getActionMethod()判断当前调用的控制器方法,实现仅update路由走自定义逻辑,其他路由保留默认的404响应 - 原代码中
$user::create()存在空对象调用风险,修正为直接用模型类User::create()
内容的提问来源于stack exchange,提问作者Angel
相关产品推荐
相关产品推荐

