whitwhoa
whitwhoa

Reputation: 2489

Laravel slugs in routes

I'm hoping this turns out to be a simple situation that I have just overlooked in the documentation. I am refactoring our web application to utilize slugs in urls. Our company allows many organizations to register, each having their own page and sub pages. I am trying to accomplish something like the below:

Route::get('/{organization-slug}', 'OrganizationController@index');
Route::get('/{organization-slug}/{organization-subpage-slug}', 'OrganizationController@subpage');
Route::get('/', 'IndexController@index');
Route::get('/dashboard', 'DashboardController@index');

However, how can I do this without conflicting with other routes? For example if I have '/{organization-slug}' this would also match for any root level route. So if a user goes to /dashboard, they would be routed to OrganizationController@index instead of DashboardController@index

Does laravel have built in functionality to handle this situation?

EDIT

In response to some of the answers stating that the order of the routes file is what needs to be revised. I have created a new laravel project to test this, and added the following routes to /routes/web.php

Route::get('/{some_id}', function($some_id){
    echo $some_id;
});
Route::get('/{some_id}/{another_id}', function($some_id, $another_id){
    echo $some_id . ' - ' . $another_id;
});
Route::get('/hardcoded/subhard', function(){
    echo 'This is the value returned from hardcoded url with sub directory';
});
Route::get('/hardcoded', function(){
    echo 'This is the value returned from hardcoded url';
});

The routes /hardcoded/subhard and /hardcoded are never reached. When this order is used. However, if we move the static routes above the dynamic like below:

Route::get('/hardcoded/subhard', function(){
    echo 'This is the value returned from hardcoded url with sub directory';
});
Route::get('/hardcoded', function(){
    echo 'This is the value returned from hardcoded url';
});
Route::get('/{some_id}', function($some_id){
    echo $some_id;
});
Route::get('/{some_id}/{another_id}', function($some_id, $another_id){
    echo $some_id . ' - ' . $another_id;
});

Then the appropriate routes appear to be working as expected. Is this correct?

Upvotes: 5

Views: 27132

Answers (4)

Mohammad Hassany
Mohammad Hassany

Reputation: 983

Order is important in route file. Put the most generic in last.


Edited:

Route::get('/', 'IndexController@index'); Route::get('/dashboard', 'DashboardController@index'); Route::get('/{organization-slug}/{organization-subpage-slug}', 'OrganizationController@subpage'); Route::get('/{organization-slug}', 'OrganizationController@index');

Upvotes: 2

Morteza Rajabi
Morteza Rajabi

Reputation: 2913

You can use Regular Expression Constraints for your routes.

Add ->where('organization-slug', '^(?!.*dashboard).*$') at the end of your parameterized routes, and they will work for any slugs except 'dashboard', and dashboard route also will work safely for http://yourdomain.com/dashboard.

Route::get('/{organization-slug}', 'OrganizationController@index')->where('organization-slug', '^(?!.*dashboard).*$');
Route::get('/{organization-slug}/{organization-subpage-slug}', 'OrganizationController@subpage')->where('organization-slug', '^(?!.*dashboard).*$');
Route::get('/dashboard', 'DashboardController@index');
Route::get('/', 'IndexController@index');

And if you have other routes like dashboard you can add them as well.

Route::get('/{organization-slug}', 'OrganizationController@index')->where('organization-slug', '^(?!.*dashboard|.*dashboard1|.*dashboard2|.*dashboard3).*$');

Upvotes: 1

Jean Marcos
Jean Marcos

Reputation: 1177

Laravel considers the last route definition for the same resource as the valid route. So just put the Route::get('/dashboard', 'DashboardController@index'); after the definition of the route of slugs:

Route::get('/{organization-slug}', 'OrganizationController@index');
Route::get('/{organization-slug}/{organization-subpage-slug}', 'OrganizationController@subpage');
Route::get('/dashboard', 'DashboardController@index');
Route::get('/', 'IndexController@index');

Upvotes: 2

ThomasRift
ThomasRift

Reputation: 98

Put Route::get('/dashboard', 'DashboardController@index'); to the top in the route file :

Route::get('/dashboard', 'DashboardController@index');
Route::get('/{organization-slug}', 'OrganizationController@index');
Route::get('/{organization-slug}/{organization-subpage-slug}', 'OrganizationController@subpage');
Route::get('/', 'IndexController@index');

Upvotes: 1

Related Questions