Question

Let's say I have 2 urls:

  • localhost/backend/admin
  • localhost/backend/admin/users

In my routes.php, I would have a route that looks like this:

Route::group(array('prefix' => 'backend', 'before' => 'auth'), function(){

    // Some methods I have on this controller are: getIndex, postUpdate, etc...
    Route::controller('admin', 'AppBackend\Controllers\Admin\AdminController');

    // Some methods I have on this controller are: getIndex, postUpdate, etc...
    Route::controller('admin/users', 'AppBackend\Controllers\Admin\Users\UsersController');
});

The problem is that when I enter admin/users into the browser, Laravel thinks that I'm trying to call a method on the AdminController and finds it doesn't exist among the methods I have for this controller. It seems it would be more ideal, if a method is not found, for Laravel to continue down the routes file and hit my admin/users route and call UsersController.

2 Possible solution that I'm not fully satisfied with:

  1. Reverse the order of the routes. This won't read as naturally as I would like it to, from top to bottom. Plus, I don't know how this solution will hold up over time with every case I have in the future.
  2. Switch to using resource routes. I don't like using PUT/DELETE when it's not supported by some browsers. I like having my own set of action words (and simply renaming and adding to the default resources is not enough or becomes clunky). See also What is the value of using PUT/DELETE with Laravel?

Are there any other good solutions?

Was it helpful?

Solution

The best way of doing routes until now is to make them all manually one by one. In this article Phil Sturgeon pushed me to start to do that and I finally realized that I was having too much trouble using resourceful and restful for a little gain.

It's better to have control of your route listing. Resourceful controllers add too much info, like route parameters, and, to make resourceful controllers not create a bunch of routes I don't use I have to filter what should be generated. In the end it was simply easier to create one route every time I was creating a functionality on my application.

As far as I can tell, to process all your routes in the correct order, Laravel builds a list of your routes, exactly the same way if we were doing it manually. So, there is no performance penalty in doing them manually.

This is an example of my routes in an application I'm just starting:

// Firewall Blacklisted IPs blocked from all routes
Route::group(['before' => 'fw-block-bl'], function()
{
    Route::group(['namespace' => 'Application\Controllers'], function()
    {
        // Pretty error message goes to this route
        Route::get('error', ['as' => 'error', 'uses' => 'Error@show']);

        Route::get('coming/soon', ['as' => 'coming.soon', 'uses' => 'ComingSoon@index']);
        Route::post('coming/soon', ['as' => 'coming.soon.post', 'uses' => 'ComingSoon@register']);
        Route::get('coming/soon/register', ['as' => 'coming.soon.register', 'uses' => 'ComingSoon@register']);
        Route::post('coming/soon/audit', ['as' => 'coming.soon.audit', 'uses' => 'ComingSoon@audit']);
        Route::get('coming/soon/activate/{code}', ['as' => 'coming.soon.activate', 'uses' => 'ComingSoon@activate']);

        // Whitelisted on firewall will have access to those routes, 
        // otherwise will be redirected to the coming/soon page
        Route::group(['before' => 'fw-allow-wl'], function()
        {
            Route::get('user/activate/{code}', ['as' => 'user/activate', 'uses' => 'User@activate']);
            Route::get('user/activation/send/{email?}', ['as' => 'user/activation', 'uses' => 'User@sendActivation']);

            Route::get('login', ['as' => 'login', 'uses' => 'Logon@loginForm']);
            Route::post('login', ['as' => 'login', 'uses' => 'Logon@doLogin']);
            Route::get('logout', ['as' => 'logout', 'uses' => 'Logon@doLogout']);

            Route::get('register', ['as' => 'register', 'uses' => 'Register@registerForm']);

            Route::get('user/recoverPassword/{code}', ['as' => 'user/recoverPassword', 'uses' => 'User@recoverPassword']);
            Route::post('user/changePassword', ['as' => 'user/changePassword', 'uses' => 'User@changePassword']);

            // Must be authenticated
            Route::group(['before' => 'auth'], function()
            {
                Route::get('/', ['as' => 'home', 'uses' => 'Home@index']);
                Route::get('profile', ['as' => 'profile', 'uses' => 'User@profile']);

                Route::group(['prefix' => 'offices'], function()
                {
                    Route::get('/', ['uses' => 'Offices@index']);
                    Route::get('create', ['uses' => 'Offices@create']);
                });

                Route::group(['prefix' => 'users'], function()
                {
                    Route::get('/', ['uses' => 'Users@index']);
                    Route::get('create', ['uses' => 'Users@create']);
                });
            });
        });
    });
});

All controllers will be namespaced in Application\Controllers and all methods (or subroutes) are prefixed.

EDIT

I'm starting to think I dont name my routes too, I'm not really using them, but I'm still not certain of this, so routes names are not really clear in this raw example. Some also have a 'uses' that could be removed and they will as soon as I decide myself by using names or not.

EDIT 2

I don't do ->before() in routes, because I like to read my routes files sometimes and this method may only be visible after a big list of routes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top