When using Route::apiResource method if you have 2 routes that end in the same URL segment, then it causes a name clash regardless of the URL, and there does not seem to be a way to define the namespace for the route, within the docs at least.
Define 2 apiResources
Route::apiResource('users/{user}/comments', 'Comments\UserCommentController');
Route::apiResource('posts/{post}/comments', 'Comments\PostCommentController');
Then the named routes end up being the same
➜ php artisan route:list --name=comments
+--------+-----------+---------------------------------------------------+------------------+-----------------------------------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+-----------+---------------------------------------------------+------------------+-----------------------------------------------------------------------+------------+
| | GET|HEAD | api/users/{user}/comments | comments.index | App\Http\Controllers\API\Comments\UserCommentController@index | api |
| | POST | api/users/{user}/comments | comments.store | App\Http\Controllers\API\Comments\UserCommentController@store | api |
| | GET|HEAD | api/users/{user}/comments/{comment} | comments.show | App\Http\Controllers\API\Comments\UserCommentController@show | api |
| | PUT|PATCH | api/users/{user}/comments/{comment} | comments.update | App\Http\Controllers\API\Comments\UserCommentController@update | api |
| | DELETE | api/users/{user}/comments/{comment} | comments.destroy | App\Http\Controllers\API\Comments\UserCommentController@destroy | api |
| | GET|HEAD | api/posts/{post}/comments | comments.index | App\Http\Controllers\API\Comments\PostCommentController@index | api |
| | POST | api/posts/{post}/comments | comments.store | App\Http\Controllers\API\Comments\PostCommentController@store | api |
| | PUT|PATCH | api/posts/{post}/comments/{comment} | comments.update | App\Http\Controllers\API\Comments\PostCommentController@update | api |
| | DELETE | api/posts/{post}/comments/{comment} | comments.destroy | App\Http\Controllers\API\Comments\PostCommentController@destroy | api |
| | GET|HEAD | api/posts/{post}/comments/{comment} | comments.show | App\Http\Controllers\API\Comments\PostCommentController@show | api |
+--------+-----------+---------------------------------------------------+------------------+-----------------------------------------------------------------------+------------+
Then if you try and swap the params around, you get a more awkward name
Route::apiResource('comments/user/{user}', 'Comments\UserCommentController');
Route::apiResource('comments/post/{post}, 'Comments\PostCommentController');
You will end up with
{user}.index,
{user}.show,
{user}.store,
{user}.destroy,
{user}.update,
It's almost like you need to be able to "name" the resource, which if used will prefix them, rather than having to do something really verbose like
Route::apiResource('user/{user}/comments', 'Comments\UserCommentController')
->names([
'index' => 'comments.users.index',
'show' => 'comments.users.show',
'store' => 'comments.users.store',
'update' => 'comments.users.update',
'destroy' => 'comments.users.destroy',
]);
If i remember correctly, you could use
Route::apiResource('user.comments', 'Comments\UserCommentController');
This would result in user.comments.* route names
@koenhoeijmakers the first param is the route pattern, so that wouldn’t work - and it doesn’t allow for the first param
It generates routes like:
user.comments.index -> user/{user}/comments
@koenhoeijmakers
Ha, that's weird, do you know if there's somewhere on the docs that explain all this? I guess it works okay if your route param, matches the model name.
I guess it is definitely a workaround, however, it would still make sense I feel to be able to name the route like you can do for normal routes
https://laravel.com/docs/5.1/controllers#restful-nested-resources
It was in the 5.1 docs, but it was removed from the docs from 5.2 and up, as Taylor doesn't think of it as that good of a practice (although to me it makes perfect sense for your situation). source
This is from memory - but with resource you can pass options as the 3rd parameter to set a prefix for the named routes. This should leave you with named routes like users.comments.index.
Route::apiResource('users/{user}/comments', 'Comments\UserCommentController', [
'as' => 'users'
]);
Can confirm the latter, which is a better solution than mine.
@dwightwatson will check this out today see how ignorant plays out :)
Most helpful comment
This is from memory - but with
resourceyou can pass options as the 3rd parameter to set a prefix for the named routes. This should leave you with named routes likeusers.comments.index.