资源控制器是针对标准crud场景的约定压缩,生成的7个方法严格对应http动作:index→get /res、create→get /res/create、store→post /res、show→get /res/{id}、edit→get /res/{id}/edit、update→put/patch /res/{id}、destroy→delete /res/{id}。

资源控制器不是“更高级”的写法,而是针对标准 CRUD 场景的**约定压缩**——它不解决复杂逻辑,但能立刻消灭 70% 的路由冗余和控制器模板代码。
资源控制器生成的 7 个方法对应哪些真实 HTTP 动作
运行 php artisan make:controller PostController --resource 后,PostController 自动包含以下方法,每个都绑定明确的请求类型和路径:
-
index()→GET /posts:列表页,不带参数 -
create()→GET /posts/create:返回新建表单视图 -
store(Request $request)→POST /posts:接收表单提交,无路由参数 -
show($id)→GET /posts/{id}:详情页,$id是路由段,可被隐式绑定为模型实例 -
edit($id)→GET /posts/{id}/edit:返回编辑表单 -
update(Request $request, $id)→PUT/PATCH /posts/{id}:更新操作,必须同时接收$request和$id -
destroy($id)→DELETE /posts/{id}:删除单条记录
这些不是“可选风格”,而是 Laravel 路由调度器硬编码识别的签名。改名(如 view() 替代 show())、漏参数(如 update(Request $request) 不带 $id),都会导致 404 或 Missing required parameter 错误。
为什么 store() 方法收不到 $id,而 show() 可以
这是资源路由设计里最容易误解的一点:store() 对应的是 POST /resources,路径中没有 ID 段,所以框架根本不会尝试注入 $id —— 即使你强行在方法签名里加了 $id,它也始终是 null 或触发绑定失败。
相反,show($id)、edit($id) 等方法的路由 URI 明确包含 {id},Laravel 才会执行模型绑定(例如 show(Post $post))或传入原始值。
常见错误现象:
-
store()中写Post::find($id)→$id为null,查不到数据 - 想用
store()创建关联资源(如带user_id),却从路由取值 → 必须从$request->input('user_id')或显式查询获取 - 把
store()当成“创建并跳转详情”入口,却忘了新记录的 ID 只有保存后才可知 → 应该用$post->id做重定向,而不是依赖路由参数
路由模型绑定在资源控制器里怎么才算生效
隐式绑定只在方法参数类型提示为具体 Eloquent 模型且路由段名称与变量名完全一致时触发。例如:
- ✅
show(Post $post)+ 路由/posts/{post}→ 绑定成功,$post是模型实例 - ❌
show(Post $p)→ 变量名$p≠ 路由段{post}→ 绑定失效,$p是字符串 ID - ❌
show($id)→ 无类型提示 → 绑定不触发,$id是字符串 - ⚠️
Route::resource('posts', PostController::class)->parameters(['posts' => 'slug'])→ 路由段变成{slug},但方法仍写show(Post $post)→ 绑定失效,$post是字符串slug值,不是模型
一旦改了参数别名,就必须同步改方法签名(如 show(Post $slug))或放弃隐式绑定,手动查模型。
什么时候不该用资源控制器
它只适合“标准资源行为”。遇到以下情况,硬套资源控制器反而增加维护成本:
- 需要支持批量操作(如
POST /posts/bulk-delete)→ 必须额外定义非标准路由,无法复用资源语义 - 一个控制器要管理多个模型(如
OrderController同时处理订单、支付、物流)→ 违反单一职责,应拆服务或用普通控制器 - URL 要高度定制(如
/dashboard/users/active、/api/v2/posts/popular)→ 资源路由的固定路径模式不适用 - 前后端分离项目中,API 需要 JSON 响应但又要求字段嵌套、分页结构特殊 →
index()返回response()->json(...)没问题,但后续扩展易失控,更适合用 API Resource 或专用 Action 类
真正容易被忽略的是:资源控制器的“约定”是双向的——你省了写 7 行路由的功夫,但也锁死了这 7 个动作的路径、方法、参数结构。一旦业务开始偏离 CRUD,第一反应不应该是“怎么 hack 它”,而是“它本就不该在这儿”。











