Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Request]: option to use 'as' in Route::resource (to improve localization prefix usage) #1616

Closed
cristianszwarc opened this issue Jun 11, 2013 · 11 comments

Comments

@cristianszwarc
Copy link

(sorry if this is not the place to share this, I searched for this but I don't found nothing related, I have fear to make an stupid point here)

description:
when you use a Route::resource inside a prefixed group, the routes for the resource are automatically defined, and it is great, but when you need to use a variable prefix (for example a language) the prefix is attached to the named route and is a shame because you need to take care of this prefix in the named route each time you use the url generator

example:

$locale = Request::segment(1); /* with some control about default and so on */ 

Route::group(array('prefix' => $locale), function()
{
    Route::group(array('prefix' => 'admin', 'before' => 'auth.admin'), function() {
        Route::resource('users', 'UsersController');
    });
    Route::get('/', array('as' => 'home', 'uses' => 'HomeController@index') );
}); 

if the $locale is 'es' then the named route will be: es.admin.users.index
and so on:
en.admin.users.index
it.admin.users.index

and in the blade template you must have:

{{ link_to_route('en.admin.users.create', 'Add new user') }}

or

{{ link_to_route('it.admin.users.create', 'Add new user') }}

walkthrough: (for this case)
A) we can generate each route manually and use the 'as' option
B) concatenate the $locale in each link_to_route

suggestion:
add an 'as' option to the Route::resource
Route::resource('users', array('as' => 'admin.users', 'uses' => 'UsersController'));

@taylorotwell
Copy link
Member

I would suggest a different way of specifying locale. I can't see us baking this kind of complexity into the router.

@cristianszwarc
Copy link
Author

I understand. The locale is just an example of this, the deal is take an extra control over the named routes of resources.
Sorry if I didn't know how complex this is. Thanks for taking the time to give a response, keep working.

@joakimkejser
Copy link

I see this being useful for configurable prefixed routes.

Say that you want to be able to change the prefix for the admin routes.

Route::group(array('prefix' => Config::get('prefix'), 'as' => 'admin'), function() {
    Route::resource('users', 'UsersController');
}

So that you can use resource routes and know the prefix without having to get the config option or variable.

URL::route('admin.users.index');

instead of something like

URL::route(Config::get('prefix') . '.users.index');

I might have misunderstood something, and I understand it might complicate the router. But it something that's been bothering me with route groups and resource routes.

@cristianszwarc
Copy link
Author

@joakimkejser Yes, you got the idea. I was thinking on an 'as' option under the options array of Route::resource then you can use nested groups and maintain the same relations inside a controller or inside a view without taking care about how deep are the prefixes

my original suggestion is wrong because I put the class under an array, totally weird and complex, but this can easily be an option under the third Route::resource parameter;

here is an updated example using the options array to set the 'as':

Route::group( array('prefix' => 'a'), function() {
   Route::group( array('prefix' => 'b'), function()
   {
        Route::resource('users', 'UsersController', 
            array('as'=>'custom.name', 'only' => array('index', 'show'))
        );
   }); 
}); 

without the 'as' option (actual behaviour) the names will be:

a.b.users.index 
a.b.users.show

with the 'as' option the names will be:

custom.name.index 
custom.name.show

with the 'as' option the Route::resource can ignore the creation of the name with all the nested prefixes and only create the names using the 'as' and ending it with the standard .index / .create / .store etc.

(disclaimer: my English is a work in progress. When I say "can easily be" is because I'm thinking if the others routes can have the 'as' option then this can be done in the resource too. When I tried to follow the code, to make a patch I notice that my Knowledge is not enough)

@mgustafsson1
Copy link

@cristianszwarc @joakimkejser Did you guys find a solution for this? I use the prefix for my locale too (haven't found a better way (browser headers for accepted language is not an option)?) and it breaks the naming of all my resource routes, unless I pass around the the prefix key like:

$routeName = $currentLang.'dogs.index';
return Redirect::route($routeName);

@cristianszwarc
Copy link
Author

No solution to give custom names to Route::resource , your workaround is one way to keep using Route::resource with the locale prefix

You can avoid the use of Route::resource and define each route for GET, PUT, DELETE etc.. but you will end with a messy router file

In simple front ends, you can use something like this:

$lng=Config::get('app.locale');   //default lang English as an example
$languages = array('es', 'gr');  //available lenguages (without the default language)
$locale = Request::segment(1);

if(in_array($locale, $languages)){
    \App::setLocale($locale);   //to change the lang over the entire app
    Config::set('app.locale', $locale);
    $lng=$locale;
}else{
    $locale = null;  //no prefix for the default lang
}

Route::group(array('prefix' => $locale), function()
{
    //home
    Route::get('/', array('as' => 'home', 'uses' => 'HomeController@index') );

    //some list
    Route::get('/products', array('as' => 'productList', 'uses' => 'ProductsController@list') );
    Route::get('/products/{id}', array('as' => 'productShow', 'uses' => 'ProductsController@show') );

});

in this example you will have 3 homes:

/    (default language)
/es
/gr

and the same with the products

/products
/es/products
/gr/products

/products/1
/es/products/1
/gr/products/1

in your controllers or views you can use {{ link_to_route('productShow', 'Show item 1', 1) }} without taking care of the selected language

browser headers it's ok as a first detection method, but when you need good SEO or a cleaner varnish interaction, then sessions or browser headers are not an option.

@mgustafsson1
Copy link

Thanks for your detailed explanation.
Yes, that's similar to the setup I have now. It only gets problematic when using resource routes within a group.

Agree about the browser headers. Also, I don't want the browser to decide which language to be shown - it's better for the user if that can be controlled through the URL, IMHO.

@gvsrepins
Copy link

👍 Definitely we need more control over the name of the resource routes. The @cristianszwarc solution looks very practical to me.

@hettiger
Copy link
Contributor

+1

@kovpack
Copy link

kovpack commented Nov 4, 2014

@cristianszwarc
I've encountered the same problem when was trying to add language parameter to URLs. Unfortunately, Laravel still has no as param for route groups, so our control over route names is limited here. But I've done localization of routes differently: instead of adding language at the beginning of every URL I've chosen Google's approach and added lang parameter to every route, having just overridden the native Laravel route helper. Full explanation is here - http://stackoverflow.com/questions/26724779/laravel-localization-and-named-routes-in-case-of-nested-routegroups/26739501#26739501
As a result - you do not have to define all GET, POST etc. routes manually, you can still use resources and have nice route names + you have good alternative to localization prefixes.

@cristianszwarc
Copy link
Author

@kovpack thanks for sharing, I will give it a try

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants