Quando se trata do backend, os desenvolvedores encontram eventualmente rotas. As rotas podem ser consideradas o espinha dorsal do backend, já que cada requisição que o servidor recebe é redirecionada para um controlador através de uma lista de roteamento que mapeia as requisições para os controladores ou ações.

Laravel esconde muitos detalhes de implementação e vem com muito açúcar sintáctico para ajudar tanto desenvolvedores novos quanto experientes a desenvolver seus aplicativos web.

Daremos uma olhada de perto em como gerenciar as rotas no Laravel.

Routing e Cross-Site Scripting no Laravel

Em um servidor, existem tanto rotas públicas quanto privadas. Rotas públicas podem ser um motivo de preocupação devido à possibilidade de cross-site scripts (XSS), um tipo de ataque de injeção que pode deixar você e seus usuários vulneráveis a agentes mal-intencionados.

O problema é que um usuário pode ser redirecionado de uma rota que não requer um token de sessão para uma que o faça – e ele ainda terá acesso sem o token.

A maneira mais simples de resolver este problema é aplicar um novo cabeçalho HTTP, adicionando “referrer” à rota para mitigar este cenário:

'main' => [
  'path' => '/main',
  'referrer' => 'required,refresh-empty',
  'target' => ControllerDashboardController::class . '::mainAction'
]

Rotas básicas no Laravel

No Laravel, as rotas permitem que os usuários encaminhem a solicitação apropriada ao controlador desejado. A Rota Laravel mais básica aceita um Identificador Uniforme de Ativos (seu caminho de rota) e um fechamento que pode ser tanto uma função quanto uma classe.

As rotas são criadas dentro dos arquivos web.php e api.php. Laravel vem com duas rotas por padrão: uma para a WEB e outra para a API.

Estas rotas residem nas rotas/ pasta, mas elas são carregadas no arquivo Providers/RouteServiceProvider.php.

Estado padrão do prestador de serviços de rota do Laravel
Estado padrão do prestador de serviços de rota do Laravel.

Ao invés de fazer isso, podemos carregar as rotas diretamente no RouteServiceProvider.php, pulando completamente as rotas/ pasta.

Carregando as rotas do Laravel diretamente no provedor
Carregando as rotas do Laravel diretamente no provedor.

Redirecionamentos

Quando definimos uma rota, geralmente queremos redirecionar o usuário que tenha acesso, e as razões para isso variam muito. Pode ser porque é uma rota depreciada e mudamos o backend ou o servidor, ou pode ser porque queremos instalar autenticação de dois fatores (2FA), e assim por diante.

Laravel tem uma maneira fácil de fazer isso. Graças à simplicidade da framework, podemos usar o método de redirecionamento no frontend da Rota, que aceita a rota de entrada e a rota para ser redirecionada.

Opcionalmente, podemos dar o código de status para o redirecionamento como o terceiro parâmetro. O método permanentRedirect fará o mesmo que o método redirect, exceto que ele sempre retornará um código de status 301:

// Simple redirect
Route::redirect("/class", "/myClass");

// Redirect with custom status
Route::redirect("/home", "/office", 305);

// Route redirect with 301 status code
Route::permanentRedirect("/home", "office");

Dentro das rotas de redirecionamento, estamos proibidos de usar as palavras-chave “destination” e “status” como parâmetros, pois elas são reservadas pelo Laravel.

// Illegal to use
Route::redirect("/home", "/office/{status}");

Visualizações

As visualizações são os arquivos .blade.php que usamos para renderizar o frontend da nossa aplicativo Laravel. Ele usa o mecanismo de templates de lâmina, e é a maneira padrão para construir um aplicativo de stack completo usando apenas Laravel.

Se quisermos que nossa rota retorne uma visualização, podemos simplesmente usar o método de visualização na frontend da Rota. Ele aceita um parâmetro de rota, um nome de visualização e um conjunto opcional de valores a serem passados para a visualização.

// When the user accesses my-domain.com/homepage
// the homepage.blade.php file will be rendered
Route::view("/homepage", "homepage");

Vamos assumir que nossa visualização quer dizer “Olá, {name}“, passando um array opcional com esse parâmetro. Podemos fazer exatamente isso com o seguinte código (se o parâmetro ausente for requerido na visualização, o pedido falhará e lançará um erro):

Route::view('/homepage', 'homepage', ['name' => "Kinsta"]);

Lista de rotas

À medida que seu aplicativo crescer, também crescerá o número de solicitações que precisam ser encaminhadas. E com um grande volume de informações pode haver uma grande confusão.

Aqui é onde o artisan route:list command pode nos ajudar. Ele fornece uma visão geral de todas as rotas definidas no aplicativo, seus middlewares e controllers.

php artisan route:list

Ele exibirá uma lista de todas as rotas sem os middlewares. Para isso, temos que usar a flag -v:

php artisan route:list -v

Em uma situação em que você pode estar usando um projeto orientado por domínio onde suas rotas têm nomes específicos em seus caminhos, você pode usar as capacidades de filtragem deste comando dessa forma:

php artisan route:list –path=api/account

Isto mostrará apenas as rotas que começam com api/account.

Por outro lado, podemos instruir Laravel de excluir ou incluir rotas definidas por terceiros, usando as opções –except-vendor ou –only-vendor.

Parâmetros de rotas

Algumas vezes você pode precisar capturar segmentos do URI com a rota, como um ID de usuário ou um token. Podemos fazer isso definindo um parâmetro de rota, que está sempre enclausurado em chaves em colchete ({}) e deve consistir apenas de caracteres alfabéticos.

Se nossas rotas tiverem alguma dependência em callbacks, o contêiner de serviço do Laravel irá incluí-los automaticamente:

use IlluminateHttpRequest;
use Controllers/DashboardController;
Route::post('/dashboard/{id}, function (Request $request, string $id) {
  return 'User:' . $id;
}
Route::get('/dashboard/{id}, DashboardController.php);

Parâmetros requeridos

Os parâmetros obrigatórios do Laravel são parâmetros de rota que não podemos omitir ao fazer uma chamada. Caso contrário, um erro será retornado:

Route::post("/gdpr/{userId}", GetGdprDataController.php");

Agora dentro do GetGdprDataController.php teremos acesso direto ao parâmetro $userId.

public function __invoke(int $userId) {
  // Use the userId that we received…
}

Uma rota pode tomar qualquer número de parâmetros. Eles são injetados nos callbacks/controllers da rota com base na ordem em que são listados:

 // api.php
Route::post('/gdpr/{userId}/{userName}/{userAge}', GetGdprDataController.php);
// GetGdprDataController.php
public function __invoke(int $userId, string $userName, int $userAge) {
  // Use the parameters…
}

Parâmetros opcionais

Em uma situação em que queremos fazer algo em uma rota quando apenas um parâmetro está presente e nada mais, tudo sem afetar todo o aplicativo, podemos adicionar um parâmetro opcional. Estes parâmetros opcionais são indicados pelo ? anexado a eles:

 Route::get('/user/{age?}', function (int $age = null) {
  if (!$age) Log::info("User doesn't have age set");
  else Log::info("User's age is " . $age);
}
Route::get('/user/{name?}', function (int $name = "John Doe") {
  Log::info("User's name is " . $name);
}

Rotas wildcard

Laravel permite que você filtre como os parâmetros opcionais ou obrigatórios são exibidos.

Digamos que queremos uma sequência de identificação do usuário. Podemos validá-lo assim no nível da rota usando o método where.

O método where aceita o nome do parâmetro e a regra regex que será aplicada na validação. Por padrão, ele aceita o primeiro parâmetro, mas se tivermos muitos, podemos passar um array com o nome do parâmetro como a chave e a regra como o valor, e Laravel irá analisá-los todos para nós:

Route::get('/user/{age}', function (int $age) {
  //
}->where('age', '[0-9]+');
Route::get('/user/{age}', function (int $age) {
  //
}->where('[0-9]+');
Route::get('/user/{age}/{name}', function (int $age, string $name) {
  //
}->where(['age' => '[0-9]+', 'name' => '[a-z][A-z]+');

Podemos levar isso um passo adiante e aplicar a validação em todas as rotas em nosso aplicativo, usando o método pattern no frontend Route:

 Route::pattern('id', '[0-9]+');

Isso irá valer cada parâmetro id com esta expressão regex. E uma vez definida, ela será automaticamente aplicada a todas as rotas usando esse nome de parâmetro.

Como podemos ver, Laravel está usando o personagem / como um separador no caminho. Se quisermos usá-lo no caminho, temos que permitir explicitamente que ele faça parte do nosso espaço reservado usando um regex where.

 Route::get('/find/{query}', function ($query) {
  //
})->where('query', , '.*');

A única desvantagem é que ele será suportado apenas no último segmento de rota.

Rotas nomeadas

Como o nome sugere, podemos nomear rotas, o que torna conveniente gerar URLs ou redirecionar para rotas específicas.

Como criar rotas nomeadas

Uma maneira simples de criar uma rota nomeada é fornecida pelo método name acorrentado no frontend Route. O nome de cada rota deve ser único:

 Route::get('/', function () {
})->name("homepage");

Grupos de rotas

Grupos de rotas permitem que você compartilhe atributos de rotas como middlewares por inúmeras rotas sem a necessidade de redefini-la em cada rota.

Middleware

A atribuição de um middleware a todas as rotas que temos nos permite combiná-las em um grupo, primeiro usando o método group. Uma coisa a ser considerada é que os middlewares são executados na ordem em que são aplicados ao grupo:

 Route:middleware(['AuthMiddleware', 'SessionMiddleware'])->group(function () {
  Route::get('/', function() {} );
  Route::post('/upload-picture', function () {} );
});

Controller

Quando um grupo utiliza o mesmo controlador, podemos usar o método controller para definir o controlador comum para todas as rotas dentro desse grupo. Agora temos que especificar o método que a rota chamará.

 Route::controller(UserController::class)->group(function () {
  Route::get('/orders/{userId}', 'getOrders');
  Route::post('/order/{id}', 'postOrder');
});

Rotas do subdomínio

Um nome de subdomínio é uma parte de informação adicional adicionado ao início do nome de domínio de um site. Isso permite que os sites separem e organizem seu conteúdo para funções específicas, tais como lojas on-line, blogs, apresentações, etc., do resto do site.

Nossas rotas podem ser usadas para lidar com o roteamento de subdomínios. Podemos pegar o domínio e uma parte do subdomínio para uso em nosso controlador e rota. Com a ajuda do método domain no frontend Route, podemos agrupar nossas rotas sob um único domínio:

 Route::domain('{store}.enterprise.com')->group(function() {
  Route::get('order/{id}', function (Account $account, string $id) {
    // Your Code
  }
});

Prefixos e prefixos de nome

Sempre que temos um grupo de rotas, ao invés de modificá-las uma a uma, podemos recorrer às utilidades extras que Laravel fornece, tais como prefix e name no frontend Route.

O método prefix pode ser usado para prefixar cada rota no grupo com um determinado URI, e o método name pode ser usado para prefixar cada nome de rota com uma determinada string.

Isso nos permite criar coisas novas como rotas administrativas sem ser necessário modificar cada nome ou prefixo para identificá-las:

 Route::name('admin.")->group(function() {
  Route::prefix("admin")->group(function() {
    Route::get('/get')->name('get');
    Route::put('/put')->name(put');
    Route::post('/post')->name('post');
  });
});

Agora as URIs para estas rotas serão admin/get, admin/put, admin/post, e os nomes admin.get, admin.put, e admin.post.

Cache de rotas

Ao implantar o aplicativo nos servidores de produção, um bom desenvolvedor Laravel aproveitará o cache de rotas no Laravel.

O que é cache de rotas?

O cache de rotas diminui a quantidade de tempo que leva para registrar todas as rotas do aplicativo.

Rodando php artisan route:cache é gerada uma instância de Illuminate/Routing/RouteCollection, e após ser codificada, a saída serializada é escrita para bootstrap/cache.routes.php.

Agora qualquer outra solicitação irá carregar este arquivo de cache, se ele existir. Portanto, nosso aplicativo não tem mais que analisar e converter entradas do arquivo de rota em objetos Illuminate/Routing/Route em Illuminate/Routing/RouteCollection.

Por que é importante usar o cache de rotas

Ao não usar o recurso de cache de rotas que Laravel fornece, seu aplicativo corre o risco de funcionar mais lentamente do que poderia ser, o que, por sua vez, poderia diminuir as vendas, a retenção de usuários e a confiança em sua marca.

Dependendo da escala do seu projeto e de quantas rotas existem, executar um simples comando de cache de rotas pode acelerar seu aplicativo em qualquer lugar de 130% a 500% – um ganho maciço por quase nenhum esforço.

Resumo

O roteamento é a espinha dorsal do desenvolvimento de backend. A framework do Laravel se sobressai nisso ao fornecer uma maneira direta de definir e gerenciar rotas.

O desenvolvimento pode de fato ser acessível a todos e ajudar acelerar um aplicativo apenas em virtude de ser construída no Laravel.

Que outros truques e dicas você já encontrou com relação às rotas no Laravel? Informe na seção de comentários!

Coman Cosmin

Cosmin Coman é um escritor de tecnologia e desenvolvedor com mais de 3 anos de experiência. Além de escrever para a Kinsta, ele ajudou em pesquisas em instalações de física nuclear e universidades. Com grande conhecimento técnico e integrado à comunidade, ele sempre vem com soluções inovadoras.