I have a nested resource route definition like this:
Route::resource('posts.comments', 'CommentController');
That produces the following routes:
+--------+-----------+--------------------------------------+------------------------+------------------------------------------------+------------+
| 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
model:
public function comments()
{
return $this->hasMany(Comment::class);
}
Comment
model:
public function post()
{
return $this->belongsTo(Post::class);
}
posts
table:
+----+--------+-----------------------------+---------------------+---------------------+
| 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
table:
+----+---------+-----------------------------+---------------------+---------------------+
| 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 |
+----+---------+-----------------------------+---------------------+---------------------+
In the docs:
When using a custom keyed implicit binding as a nested route parameter, Laravel will automatically scope the query to retrieve the nested model by its parent using conventions to guess the relationship name on the parent.
So, {comment}
is supposed to be child of {post}
. But when I hit /posts/1/comments/2
, it retrieves comment with an id of 2 which belongs to the post with an id of 2. The expected result would be NotFoundHttpException
.
It works fine when I define the routes individually like this:
Route::get('/posts/{post}/comments/{comment:id}', 'CommentController@show');
Why is this happening?
Also tried to customize the default key name in both Post
and Comment
models:
public function getRouteKeyName()
{
return 'id';
}
But no luck.
Any help would be appreciated.
Did some digging and reached a conclusion after reading Illuminate\Routing\PendingResourceRegistration.php
class from the source code. I have to use custom keyed implicit binding to make it work as I expect.
Route::resource()
method takes (optional) third argument which is an associative array. So, I need to override the route parameter name via parameters
key using this argument.
Route::resource('posts.comments', 'CommentController', [
'parameters' => ['comments' => 'comment:id'],
]);
or
Route::resource('posts.comments', 'CommentController')->parameters([
'comments' => 'comment:id',
]);
It works either way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With