Laravel 11/Vue:软删除模型路由绑定强制删除时404错误
问题描述
在使用Laravel路由模型绑定对软删除的Recipe模型执行forceDelete()时,出现404 Not Found错误,仅在强制删除已软删除的模型时触发;恢复或软删除操作均正常。
已在edit方法中实现编辑已软删除模型时自动恢复的功能,该功能可正常运行:
RecipeController.php
// 此功能正常工作 public function edit(Recipe $recipe) { Gate::authorize('update', $recipe); if ($recipe->trashed()) { $recipe->restore(); } return Inertia::render('Recipes/Edit', [ 'recipe' => $recipe->load(['ingredients', 'steps', 'categories']), 'categories' => Auth::user()->categories ]); }
尝试在destroy方法的Gate::authorize()前添加dd($recipe),但仍直接返回404,说明路由模型绑定未找到对应模型。希望保留标准资源路由,让destroy方法自动判断执行永久删除还是软删除,询问是否必须新增方法仅传入ID处理强制删除。
相关配置及代码如下:
web.php
Route::resource('/recipes', RecipeController::class)->withTrashed();
RecipeController.php
// 软删除正常,但强制删除已软删除模型时返回404 public function destroy(Recipe $recipe) { Gate::authorize('delete', $recipe); if ($recipe->trashed()) { $recipe->forceDelete(); Storage::deleteDirectory('recipe-images/'.$recipe->id); } else { $recipe->delete(); } }
Index.vue
<Link :href="route('recipes.destroy', recipe)" method="delete" as="button" class="relative inline-flex w-0 flex-1 items-center justify-center gap-x-3 rounded-br-lg border border-transparent py-3 text-sm font-semibold text-gray-900"> <TrashIcon class="h-5 w-5 text-red-400" aria-hidden="true" /> </Link>
路由列表输出
DELETE recipes/{recipe} recipes.destroy › RecipeController@destroy
控制台错误
DELETE http://127.0.0.1:8000/recipes/9c8fa4c7-8723-4ca4-8468-5968ae7c02e3 404 (Not Found)
解决方案
问题根源:Laravel隐式路由模型绑定默认仅查询未被软删除的记录,当尝试通过路由绑定获取已软删除的模型时,系统会返回404,因为找不到匹配的未删除记录。
以下几种方案可解决问题,无需新增额外方法:
方案1:修改路由,单独为destroy方法指定withTrashed
将原资源路由拆分为普通资源路由+单独的destroy路由,确保destroy路由的参数包含软删除模型:
// 先注册除destroy外的所有资源路由 Route::resource('/recipes', RecipeController::class)->except(['destroy']); // 单独注册destroy路由并添加withTrashed约束 Route::delete('/recipes/{recipe}', [RecipeController::class, 'destroy'])->withTrashed();
方案2:在控制器destroy方法中手动查询含软删除的模型
放弃隐式路由模型绑定,改用显式查询获取包含软删除的模型:
public function destroy($id) { // 显式查询包含软删除的模型 $recipe = Recipe::withTrashed()->findOrFail($id); Gate::authorize('delete', $recipe); if ($recipe->trashed()) { $recipe->forceDelete(); Storage::deleteDirectory('recipe-images/'.$recipe->id); } else { $recipe->delete(); } // 添加响应返回,比如重定向或Inertia响应 return redirect()->route('recipes.index'); }
方案3:修改模型的路由绑定逻辑,全局包含软删除记录
在Recipe模型中重写路由绑定解析方法,让所有路由模型绑定都包含软删除的记录:
// Recipe.php模型文件 public function resolveRouteBinding($value, $field = null) { return $this->withTrashed() ->where($field ?? $this->getRouteKeyName(), $value) ->firstOrFail(); }
注意:此方案会影响所有使用该模型的路由绑定,若部分场景不需要包含软删除模型,需谨慎使用。
内容的提问来源于stack exchange,提问作者GazSte
相关产品推荐
相关产品推荐

