> LOADING ARTICLE...
28 Jul 2025 Desenvolvimento

Como estruturar as Rotas em grandes projectos Laravel?

Como estruturar as Rotas em grandes projectos Laravel?

Imagine um projeto Laravel com mais de 100 rotas, separadas para utilizadores convidados, registados, administradores, etc… Tem a certeza que quer manter essas rotas num único ficheiro??? Como podemos agrupar, adicionar prefixos às URLs? Vamos ver quais opções temos disponíveis.

Separar as rotas WEB e API

Esta é fácil e é uma funcionalidade que o Laravel oferece por defeito. Existem dois ficheiros:

  • routes/web.php
  • routes/api.php

Então, se no seu projeto tem tanto views como uma API (o que nos dias de hoje é cada vez mais comum), por favor, utilize o ficheiro routes/api.php para estruturar essas rotas.

Por exemplo, se tiver a página /users e também um endpoint /api/users, separar estas rotas nos respetivos ficheiros irá ajudar a não criar confusões de nomeações no mesmo ficheiro.

Estruturar o ficheiro routes/web.php em Groups

Esta funcionalidade também vem por defeito numa nova instalação de Laravel. Este exemplo é retirado da documentação oficial do Laravel:

Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', function () {
        // Uses first & second Middleware
    });

    Route::get('user/profile', function () {
        // Uses first & second Middleware
    });
});

A forma mais basica é “esconder” diferentes groups dentro de diferentes middlewares. Por exemplo, precisa de um group que esteja restrito por defeito ao middleware auth, e outro group para o middleware admin.

Com isto, pode usar route group names e prefixes, como mostra o exemplo abaixo:

Route::prefix('admin')->group(function () {
    Route::get('users', function () {
        // Matches The "/admin/users" URL
    });
});

Route::name('admin.')->group(function () {
    Route::get('users', function () {
        // Route assigned name "admin.users"...
    })->name('users');
});

Pode ainda adicionar tudo (middleware+name+prefix) a um unico group, fica muito mais legível colocar dentro de um array:

// Instead of chaining like this: 
Route::name('admin.')->prefix('admin')->middleware('admin')->group(function () {
    // ...
});

// You can use an array
Route::group([
    'name' => 'admin.', 
    'prefix' => 'admin', 
    'middleware' => 'auth'
], function () {
    // ...
});

Vamos então colocar tudo junto num exemplo que podia perfeitamente ser real.

  • Utilizadores Convidados (guest) – group com /front/xxxxx URLs sem qualquer middleware
  • Utilizadores registados (user) – group com /user/xxxxx URLs com middleware auth
  • Admins – group com /admin/xxxxxx URLs e com middleware admin

Deixo uma forma para agrupar rotas no ficheiro routes/web.php:

Route::group([
    'name' => 'admin.',
    'prefix' => 'admin',
    'middleware' => 'admin'
], function () {

    // URL: /admin/users
    // Route name: admin.users
    Route::get('users', function () {
        return 'Admin: user list';
    })->name('users');

});

Route::group([
    'name' => 'user.',
    'prefix' => 'user',
    'middleware' => 'auth'
], function () {

    // URL: /user/profile
    // Route name: user.profile
    Route::get('profile', function () {
        return 'User profile';
    })->name('profile');

});

Route::group([
    'name' => 'front.',
    'prefix' => 'front'
], function () {

    // No middleware here
    // URL: /front/about-us
    // Route name: front.about
    Route::get('about-us', function () {
        return 'About us page';
    })->name('about');

});

Agrupar Controllers com Namespaces

No exemplo anterior, não usámos Controllers, simplesmente retornamos texto como exemplo. Vamos adicionar Controllers com mais um “truque” – vamos estruturar os controladores em pastas com os seus próprios namespaces, como a seguir:

Depois podemos utilizar no nosso ficheiro de Routes:

Route::group([
    'name' => 'front.',
    'prefix' => 'front'
], function () {
    Route::get('about-us', 'Front\AboutController@index')->name('about');
});

Mas, e se tivermos muito controladores neste grupo? Devemos continuar a utilizar Front\QualquerController sempre??? Claro que não!!! Pode especificar o namespace como parametro também.

Route::group([
    'name' => 'front.',
    'prefix' => 'front',
    'namespace' => 'Front',
], function () {
    Route::get('about-us', 'AboutController@index')->name('about');
    Route::get('contact', 'ContactController@index')->name('contact');
});

Grupos dentro de grupos

Na situação anterior com três grupos está simplificada. Projectos reais têm pequenas diferenças na estrutura.

Imagine dois grupos: front e auth. E depois dentro de auth temos sub-grupos: user e admin. Para isso podemos criar sub-grupos e adicionar-mos diferentes middlewares e prefixos.

Route::group([
    'middleware' => 'auth',
], function() {

    Route::group([
        'name' => 'admin.',
        'prefix' => 'admin',
        'middleware' => 'admin'
    ], function () {

        // URL: /admin/users
        // Route name: admin.users
        Route::get('users', 'UserController@index')->name('users');

    });

    Route::group([
        'name' => 'user.',
        'prefix' => 'user',
    ], function () {

        // URL: /user/profile
        // Route name: user.profile
        Route::get('profile', 'ProfileController@index')->name('profile');

    });

});

Podemos fazer ainda com mais que dois niveis. Deixo um exemplo do projecto open-source Akauting:

Route::group(['middleware' => 'language'], function () {
    Route::group(['middleware' => 'auth'], function () {
        Route::group(['prefix' => 'uploads'], function () {
            Route::get('{id}', 'Common\Uploads@get');
            Route::get('{id}/show', 'Common\Uploads@show');
            Route::get('{id}/download', 'Common\Uploads@download');
        });

        Route::group(['middleware' => 'permission:read-admin-panel'], function () {
            Route::group(['prefix' => 'wizard'], function () {
                Route::get('/', 'Wizard\Companies@edit')->name('wizard.index');
        
        // ...

Definições Globais em RouteServiceProvider

O ficheiro app/Providers/RouteServiceProvider.php é onde estão todas as definições das rotas. Contém o método map() onde é feita a ligação aos dois ficheiros de rotas:

public function map()
    {
        $this->mapApiRoutes();
        $this->mapWebRoutes();
    }

    protected function mapWebRoutes()
    {
        Route::middleware('web')
             ->namespace($this->namespace)
             ->group(base_path('routes/web.php'));
    }

    protected function mapApiRoutes()
    {
        Route::prefix('api')
             ->middleware('api')
             ->namespace($this->namespace)
             ->group(base_path('routes/api.php'));
    }

Reparou que o middleware, o namespace e o prefixo estão mencionados nos métodos? Aqui é onde pode configurar todas as definições globais dos ficheiros, assim não precisa repetir em cada grupo de rotas no ficheiro.

Na maior parte das vezes é usado nas rotas de API, porque as suas configurações são normalmente as mesmas.

protected function mapApiRoutes()
{
    Route::group([
        'middleware' => ['api'],
        'namespace' => $this->namespace,
        'prefix' => 'api/v1',
    ], function ($router) {
        require base_path('routes/api.php');
    });
}

O método anterior define o prefixo de todas as URLs da API em api/v1 no seu inicio.

Agrupar Rotas em ficheiros customizados

Se você tem um elevado número de rotas e deseja agrupá-las de uma forma organizada em diferentes ficheiros, então pode usar o ficheiro já mencionado, app/Providers/RouteServiceProvider.php. Vamos ver em pormenor no método map().

public function map()
{
    $this->mapApiRoutes();

    $this->mapWebRoutes();

    //
}

Neste método pode mencionar e ligar mais ficheiros de rotas. Para isso deverá criar um novo método como por exemplo mapAdminRoutes() dentro deste ficheiro, e depois adicionar no método map(), então o seu ficheiro de rotas será registado e carregado automaticamente.

Encontrar a rota certa com o comando Artisan route:list

Já se viu perdido entre uma enormidade de número de rotas? Dispomos de um comando artisan que nos ajuda a localizar uma determinada rota.

Provavelmente já sabe que php artisan route:list devolve todas as rotas no projecto.

Mas, sabia que tem funcionalidades de filtro para procurar exatamente o que procura? Simplestemente adicione –method, –name ou –path com parametros.

Filtrar pelo método -GET, POST, etc:

Filtrar pelo nome ou URL:

Isto é tudo o que o agrupamento de rotas lhe pode oferecer em grandes projetos. Tem outros exemplos? Por favor compartilhe nos comentários.

About Post Author

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *