Route::group( ['prefix' => 'admin', 'as' => 'admin.', 'namespace' => 'Admin'], function () {
Route::group(['as' => 'user.'], function(){
Route::get('custom', [
'as' => 'custom',
'uses' => 'UserController@custom'
]);
// Results in admin.user.custom
});
Route::resource('user', 'UserController');
// Route names
// admin.admin.user.index
// admin.admin.user.create
// admin.admin.user.store
// etc..
});
I think you can see why this can be problematic, the resourcecontroller should not guess it's prefix!
I'm not skilled enough to make a good pull-request, but the problem should be somewhere here:
https://github.com/illuminate/routing/blob/5.2/ResourceRegistrar.php#L98-L128
Thanks to vsch for a workaround
source: http://laravel.io/forum/06-21-2014-resource-route-names-without-prefix
I tweaked the code for Laravel 5.2
Create App\Providers\ResourceNoPrefixRegistrar
<?php
namespace App\Providers;
use Illuminate\Routing\ResourceRegistrar;
use Illuminate\Routing\Router;
class ResourceNoPrefixRegistrar extends ResourceRegistrar
{
public function __construct(Router $router)
{
parent::__construct($router);
}
/**
* Get the resource name for a grouped resource.
*
* @param string $prefix
* @param string $resource
* @param string $method
* @return string
*/
protected function getGroupResourceName($prefix, $resource, $method)
{
// vsch: don't add prefix to the route name, if you want a prefix added to the route name add 'as' => 'prefix.' to the group options
return trim("{$prefix}{$resource}.{$method}", '.');
}
}
Add these lines to App\Providers\AppServiceProvider to the register() method
public function register()
{
$this->app->bind('Illuminate\Routing\ResourceRegistrar', function ()
{
return app('App\Providers\ResourceNoPrefixRegistrar');
});
}
Don't forget to composer dump-autoload
Thanks for the report, but I think this is intended. Please see the other issues.
I find this to be a little bit counter-intuitive. The way it's designed now, only makes sense if you never nest resource routes into groups. Once you do however, like i showed with the admin group, you have to reconstruct your routes file to make it work, and make duplicate code (if you use either namespace or middleware in routes).
Still, i would like this to be included by default, atleast as an config option.
Not sure why this should be the intended behaviour. If I want to be able to change my URL (eg from admin/students to joe/students I don't want to have to change all my route names too. I thought the intent of the 'as' parameter was to let me specify:
['prefix' => 'joe' , 'as' => 'admin' and end up with a named route of 'admin.students.index' , for example, not 'joe.admin.students.index' which is what happens. Graham - can you provide proof this is intended behaviour? Thanks.
I think it is fixed in laravel 5.3 , They are not going to fix it in 5.2 because it will break all applications using resources.
I tested L5.3 it is fixed in route group.
you will not get route group prefix in named routes.
But it is not fixed for resource controller.
resource controller still appends URI in route names
example.
Route::resource('bus', 'BusController',["as"=>"van"]);
This resources controller creates routes like this
+----------------+-----------------+
| URI | Name |
+----------------+-----------------+
| bus | van.bus.index |
| bus | van.bus.store |
| bus/create | van.bus.create |
| bus/{bus} | van.bus.show |
| bus/{bus} | van.bus.update |
| bus/{bus} | van.bus.destroy |
| bus/{bus}/edit | van.bus.edit |
+----------------+-----------------+
You can see URI is added in every named route.
So i have to use route name as
route('van.bus.index');
// It produces uri "domain.com/bus"
But what if I want to change URI to "vehicle" instead of "bus" ?
In that case if i change resource URI to vehicle
Route::resource('vehicle', 'BusController',["as"=>"van"]);
But it breaks named routes because it is using uri in route name.
So all named routes updates to following.
+------------------------+---------------------+
| URI | Name |
+------------------------+---------------------+
| vehicle | van.vehicle.index |
| vehicle | van.vehicle.store |
| vehicle/create | van.vehicle.create |
| vehicle/{vehicle} | van.vehicle.show |
| vehicle/{vehicle} | van.vehicle.update |
| vehicle/{vehicle} | van.vehicle.destroy |
| vehicle/{vehicle}/edit | van.vehicle.edit |
+------------------------+---------------------+
You can see URI is added in every named route. and all named routes are changed.
it will break my application. So i can not use old code.
route('van.bus.index');
// It produces uri "domain.com/bus"
i have to update it to
route('van.vehicle.index');
// It produces uri /bus
I have to make changes everywhere on my application which breaks principle of named route.
A word from Taylor Otwel @taylorotwell
The prefix / (uri) should not have any effect on route name
Taylor Otwell https://github.com/laravel/framework/pull/12072#issuecomment-180024098
+------------------------+-------------+
| URI | Name |
+------------------------+-------------+
| vehicle | van.index |
| vehicle | van.store |
| vehicle/create | van.create |
| vehicle/{vehicle} | van.show |
| vehicle/{vehicle} | van.update |
| vehicle/{vehicle} | van.destroy |
| vehicle/{vehicle}/edit | van.edit |
+------------------------+-------------+
so i don't have to change anything in my code.
It should be fixed in laravel 5.3
@Dmitrev @fbloggs We have to reopen issue with proper detail so they can understand what is the problem.
I already opened issue https://github.com/laravel/framework/issues/13219#issuecomment-212251605 but @GrahamCampbell closed it without reason.
you can see above quote from taylor he don't want prefix to affect route names.
You can see URI is added in every named route.
But it wasn't. In your first example the as is only added to the name, not the URI.
@taylorotwell In my first example generated route names are
Route::resource('bus', 'BusController',["as"=>"van"]);
//routes
+----------------+-----------------+
| URI | Name |
+----------------+-----------------+
| bus | van.bus.index |
| bus | van.bus.store |
| bus/create | van.bus.create |
| bus/{bus} | van.bus.show |
| bus/{bus} | van.bus.update |
| bus/{bus} | van.bus.destroy |
| bus/{bus}/edit | van.bus.edit |
+----------------+-----------------+

Where you can see "bus" (which is an URI) is added in middle of every route name van.bus.index.
So route names are like van.URI.index
But as i defined route name explicitly ["as"=>"van"] Route name should be van.index (defined route name + method name). what is the need of "bus" in route name.
It is working fine for custom methods.
Route::get('students', ['as'=> 'admin.index', 'uses' => 'StudentController@index']);
// Route name
"admin.index"
//if i change uri to "staff"
Route::get('staff', ['as'=> 'admin.index', 'uses' => 'StudentController@index']);
// Route name is still same
"admin.index"
In this example If i change uri students to staff it will not change my route name or it does not add /include 'student' in my route name. my route name always be "admin.index". And this is correct behavior of route names.
But with resource controller if i change uri bus to anything you will get route name as "van.(anything URI).index" , new route name every time. It should behave same as custom method as above.
So achieve ideal route names we have to write hefty 7/8 lines of code
// to achieve this
+----------------+-------------+
| URI | Name |
+----------------+-------------+
| bus | van.index |
| bus | van.store |
| bus/create | van.create |
| bus/{bus} | van.update |
| bus/{bus} | van.destroy |
| bus/{bus} | van.show |
| bus/{bus}/edit | van.edit |
+----------------+-------------+
// Code have to write for routes
Route::get('bus', ['as'=> 'van.index', 'uses' => 'BusController@index']);
Route::post('bus', ['as'=> 'van.store', 'uses' => 'BusController@store']);
Route::get('bus/create', ['as'=> 'van.create', 'uses' => 'BusController@create']);
Route::put('bus/{bus}', ['as'=> 'van.update', 'uses' => 'BusController@update']);
Route::patch('bus/{bus}', ['as'=> 'van.update', 'uses' => 'BusController@update']);
Route::delete('bus/{bus}', ['as'=> 'van.destroy', 'uses' => 'BusController@destroy']);
Route::get('bus/{bus}', ['as'=> 'van.show', 'uses' => 'BusController@show']);
Route::get('bus/{bus}/edit', ['as'=> 'van.edit', 'uses' => 'BusController@edit']);
And as i know use of resource controller is to save those repetitive lines and remove that mess in route file.
Above output should be achieved by resource controller.
So the problem is that first parameter is used for building both name and uri for the route. What would I do is to assume that first parameter Route::resource('name', ... is a name, and then pass additional option that would specify a base uri.
For example in the ResourceRegistrar add to the method something like this:
public function getResourceUri($resource, $options = [])
{
$resource = array_get($options, 'uri', $resource);
You would use it like this Route::resource('bus', 'BusController',['uri'=>'van']); and when you want to change the uri do something like Route::resource('bus', 'BusController',['uri'=>'vehicle']);
Other way would be to specify first parameter as uri, and as option as a base for building route names. Route::resource('uri', 'BusController', [ 'as' => 'van' ]); I would expect it to work this way but now it is just prepending as option to the generated route names, and you can see it in the getGroupResourceName method:
$prefix = isset($options['as']) ? $options['as'] . '.' : '';
Other way would be to specify first parameter as uri, and as option as a base for building route names. Route::resource('uri', 'BusController', [ 'as' => 'van' ]); I would expect it to work this way but now it is just prepending as option to the generated route names, and you can see it in the getGroupResourceName method:
$prefix = isset($options['as']) ? $options['as'] . '.' : '';
That's true @dam1r89 .
It should replace old generated route name with "as" option passed & not just prepend as to old generated route name.
@taylorotwell I think you have understood what is the problem here.
This is exactly the solution.Â
Thanks everyone.Â
Duncan
Get Outlook for iOS
On Fri, Jul 8, 2016 at 10:20 AM -0700, "john5db" [email protected] wrote:
Other way would be to specify first parameter as uri, and as option as a base for building route names. Route::resource('uri', 'BusController', [ 'as' => 'van' ]); I would expect it to work this way but now it is just prepending as option to the generated route names, and you can see it in the getGroupResourceName method:
$prefix = isset($options['as']) ? $options['as'] . '.' : '';
That's true @dam1r89 .
It should replace old generated route name with "as" option passed & not just prepend as to old generated route name.
@taylorotwell I think you have understood what is the problem here.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
Using Laravel 5.3.9
See comment from "john5db commented on 6 Jul • edited".
It describes perfectly the problem.
Route::controller('bus', 'BusController',["as"=>"van"]);
Is it possible controller instead of resource ?
Most helpful comment
@taylorotwell In my first example generated route names are
Where you can see "bus" (which is an URI) is added in middle of every route name van.bus.index.
So route names are like van.URI.index
But as i defined route name explicitly ["as"=>"van"] Route name should be van.index (defined route name + method name). what is the need of "bus" in route name.
It is working fine for custom methods.
In this example If i change uri students to staff it will not change my route name or it does not add /include 'student' in my route name. my route name always be "admin.index". And this is correct behavior of route names.
But with resource controller if i change uri bus to anything you will get route name as "van.(anything URI).index" , new route name every time. It should behave same as custom method as above.
So achieve ideal route names we have to write hefty 7/8 lines of code
And as i know use of resource controller is to save those repetitive lines and remove that mess in route file.
Above output should be achieved by resource controller.