首页 > 解决方案 > Laravel 7 - 嵌套资源路由中的范围问题

问题描述

路线:

我有一个这样的嵌套资源路由定义:

Route::resource('posts.comments', 'CommentController');

这会产生以下路线:

+--------+-----------+--------------------------------------+------------------------+------------------------------------------------+------------+
| Domain | Method    | URI                                  | Name                   | Action                                         | Middleware |
+--------+-----------+--------------------------------------+------------------------+------------------------------------------------+------------+
|        | GET|HEAD  | posts/{post}/comments                | posts.comments.index   | App\Http\Controllers\CommentController@index   | web        |
|        | POST      | posts/{post}/comments                | posts.comments.store   | App\Http\Controllers\CommentController@store   | web        |
|        | GET|HEAD  | posts/{post}/comments/create         | posts.comments.create  | App\Http\Controllers\CommentController@create  | web        |
|        | GET|HEAD  | posts/{post}/comments/{comment}      | posts.comments.show    | App\Http\Controllers\CommentController@show    | web        |
|        | PUT|PATCH | posts/{post}/comments/{comment}      | posts.comments.update  | App\Http\Controllers\CommentController@update  | web        |
|        | DELETE    | posts/{post}/comments/{comment}      | posts.comments.destroy | App\Http\Controllers\CommentController@destroy | web        |
|        | GET|HEAD  | posts/{post}/comments/{comment}/edit | posts.comments.edit    | App\Http\Controllers\CommentController@edit    | web        |
+--------+-----------+--------------------------------------+------------------------+------------------------------------------------+------------+

关系(在模型中):

Post模型:

public function comments()
{
    return $this->hasMany(Comment::class);
}

Comment模型:

public function post()
{
    return $this->belongsTo(Post::class);
}

虚拟数据(在表格中):

posts桌子:

+----+--------+-----------------------------+---------------------+---------------------+
| id | title  | body                        | created_at          | updated_at          |
+----+--------+-----------------------------+---------------------+---------------------+
| 1  | Post 1 | This is the body of Post 1. | 2020-07-29 11:20:53 | 2020-07-29 11:20:53 |
| 2  | Post 2 | This is the body of Post 2. | 2020-07-29 11:21:13 | 2020-07-29 11:21:13 |
+----+--------+-----------------------------+---------------------+---------------------+

comments桌子:

+----+---------+-----------------------------+---------------------+---------------------+
| id | post_id | body                        | created_at          | updated_at          |
+----+---------+-----------------------------+---------------------+---------------------+
| 1  | 1       | The comment for the Post 1. | 2020-07-29 11:22:27 | 2020-07-29 11:22:27 |
| 2  | 2       | The comment for the Post 2. | 2020-07-29 11:22:32 | 2020-07-29 11:22:32 |
+----+---------+-----------------------------+---------------------+---------------------+

文档中:

当使用自定义键控隐式绑定作为嵌套路由参数时,Laravel 将自动限定查询范围以通过其父级检索嵌套模型,使用约定来猜测父级上的关系名称。

所以,{comment}应该是 的孩子{post}。但是当我点击时/posts/1/comments/2,它会检索id 为2的评论,该评论属于id为2的帖子。预期的结果是。NotFoundHttpException

当我像这样单独定义路由时,它工作正常:

Route::get('/posts/{post}/comments/{comment:id}', 'CommentController@show');

为什么会这样?

还尝试在PostComment模型中自定义默认键名:

public function getRouteKeyName()
{
    return 'id';
}

但没有运气。

任何帮助,将不胜感激。

标签: phplaravellaravel-7

解决方案


从源代码Illuminate\Routing\PendingResourceRegistration.php阅读类后做了一些挖掘并得出结论。我必须使用自定义键控隐式绑定才能使其按预期工作。

Route::resource()方法采用(可选)第三个参数,它是一个关联数组。因此,我需要parameters使用此参数通过键覆盖路由参数名称。

Route::resource('posts.comments', 'CommentController', [
    'parameters' => ['comments' => 'comment:id'],
]);

或者

Route::resource('posts.comments', 'CommentController')->parameters([
    'comments' => 'comment:id',
]);

无论哪种方式都可以。


推荐阅读