Laravel 9 中嵌套资源路由需分步定义:先注册父资源 Route::resource('posts', PostController::class)->only(['index', 'show']),再用 Route::resource('posts.comments', CommentController::class)->scoped() 显式声明嵌套关系并自动绑定模型参数。

Laravel 9 中定义嵌套资源路由(比如 /posts/{post}/comments)不能靠简单套用 Route::resource() 实现,必须显式控制参数绑定、命名前缀和动作注册逻辑,否则容易出现模型注入失败、URL 生成错误或 404。
先写父路由,再显式定义子级
不要写成 Route::resource('posts.comments', CommentController::class) —— 这种写法 Laravel 不识别为嵌套,会当成一个叫 posts.comments 的独立资源,参数名也变成 {posts.comments},完全不可用。
正确做法是分两步:
- 先注册父资源:
Route::resource('posts', PostController::class)->only(['index', 'show']); - 再单独定义子级路由,显式写出 URI 模板:
Route::resource('posts.comments', CommentController::class)->scoped();
->scoped() 的作用是让 Laravel 自动把 {post} 绑定到 Post 模型,并在控制器方法中注入 Post $post;同时子资源的 {comment} 也会按惯例绑定 Comment 模型。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
注意参数名和控制器签名必须一致
默认情况下,posts.comments 路由生成的 URI 是 /posts/{post}/comments/{comment},参数名是 post 和 comment。这意味着:
- CommentController 的
show方法签名得是:public function show(Post $post, Comment $comment) - 不能只写
Comment $comment,否则$post注入失败,Laravel 找不到匹配的 route key - 如果模型主键不是
id(比如用了slug),还要同步改参数名:->parameters(['posts' => 'post_slug', 'comments' => 'comment_slug']),并调整控制器方法参数名和类型提示
命名和中间件要手动叠加
嵌套资源的路由名默认是 posts.comments.index 这类,但如果你放在路由组里(比如 API 版本前缀),必须显式配 as 前缀:
Route::prefix('api/v1')->as('api.v1.')->group(function () { Route::resource('posts.comments', CommentController::class)->scoped(); });- 这样生成的路由名才是
api.v1.posts.comments.index,调用route('api.v1.posts.comments.show', [$post, $comment])才能成功 - 中间件不会自动继承,要在 group 里统一加:
->middleware('auth:sanctum'),或者给子资源单独链式调用->middleware(...)
生成 URL 时必须传全参数,顺序不能错
调用 route() 生成嵌套资源链接时,参数顺序必须严格对应 URI 占位符顺序:
-
route('posts.comments.show', [$post, $comment])✅ 正确({post}在前,{comment}在后) -
route('posts.comments.show', [$comment, $post])❌ 报错 “Missing required parameter” - 推荐传模型实例而非 ID,避免后期切换 UUID 或主键类型时漏改所有
route()调用点


















