Blog EspecializaTi
Carlos Ferreira Por: Carlos Ferreira Comentar

Rotas no Laravel

Rotas no Laravel

Se pesquisar pela definição de rotas vai encontrar centenas de tutoriais com teorias super mirabolantes sobre este assunto, mas particularmente gosto de ser mais breve e objetivo e definir rotas como URL AMIGÁVEIS.
Imagine que temos uma aplicação que acessamos ela pelo seu endereço de domínio www.especializati.com.br/

Quando acessamos www.especializati.com.br estamos utilizando a rota “/”
Quando acessamos www.especializati.com.br/contato estamos utilizando a rota “/contato”
Quando acessamos www.especializati.com.br/empresa estamos utilizando a rota “/empresa”

Este é o conceito de rotas, no laravel, ao receber uma requisição em uma determinada URL o sistema de rotas define o que fazer, como por exemplo redirecionar ou enviar para o controlador (Controller) decidir o que fazer.

 

 

Verbos HTTP:

O sistema de rotas do laravel permite registrar método de rotas para todos os verbos http disponíveis, os tipos de rotas disponíveis são:

$this->get($uri, $callback);
$this->post($uri, $callback);
$this->put($uri, $callback);
$this->patch($uri, $callback);
$this->delete($uri, $callback);
$this->options($uri, $callback);

Rotas do tipo GET é para retornar algo, como por exemplo uma listagem de conteúdo e etc.
Rotas do tipo POST normalmente são utilizados para cadastrar algo no sistema.
Rotas do tipo PUT ou PATH são para editar algum registro.
Rotas do tipo de DELETE são para deletar algo.
E por último, rotas do tipo OPTIONS

 

A diferença entre $this e Route:
É possível definir rotas de 2 formas, a mais comum é utilizar a própria classe e chamar um método estático:

Route::get('url', $callback);

 

É possível utilizar o $this, o this faz referência a própria classe Route, assim pode chamar o métodos desta forma:

$this->get('url', $callback);

Eu particularmente prefiro utilizar o $this->, primeiro porque é utiliza menos códigos, e também porque é uma instância da classe e não precisa utilizar um método estático (Chamar um método estático é mais lento que utilizar um objeto, mas enfim, isso não entra em discussão aqui).

 

 

Criando rotas no laravel:

O arquivo de rotas fica em /routes/web.php, todas rotas da aplicação web devem ficar neste arquivo.
NOTA: No arquivo web.php deve ficar apenas as rotas da aplicação e não as rotas de API, rotas de API devem ficar em /routes/api.php

Rota GET:

$this->get('user', function(){
	return 'Olá, user!';
});

Ao acessar http://sua-app.dev/user vai retornar o texto “Olá, user!”, porque neste caso definimos a url como “user” e no segundo parâmetro do método get() passamos uma função de callback que retorna este texto.

Não é recomendado retornar uma função de callback desta forma, o ideal é passar a responsabilidade para o controlador (Controller) e ele por sua vez se vira e repassa as responsabilidades.
Veja o exemplo, correto:

$this->get('user', '[email protected]');

Agora sim, ao acessar http://sua-app.dev/user vai utilizar o controller que está em /app/Http/Controllers/NomeController e o método nomeMetodo() deste controller.

Rota POST:

$this->post('usuario', '[email protected]');

Ao acessar http://sua-app.dev/usuario com o verbo http POST vai acessar essa rota.

Utilizado para inserir um novo registro, normalmente utilizado por requisições a partir de formulários ou requisições externas por API.

Proteção contra ataques CSRF:
Rotas do tipo POST tem proteção automática no laravel contra ataques CSRF. Esse tipo de ataque tem o objetivo de enviar de maneira fake um número muito grande requisições para o sistema. Ataques CSRF se não proteger pode inserir uma quantidade ilimitada de registros no banco de dados até derrubar o banco de dados.

O laravel uma sessão com um token único que sempre que utilizado é atualizado para proteção contra esse tipo de ataque. Sempre que fizer uma requisição com o verbo http post precisa enviar este token para validar a requisição (Veja o valor do token chamando o método: csrf_token()).

Como enviar o token para uma requisição post, basta adicionar este item ao formulário que irá fazer a requisição POST:

<form method="POST" action="/usuario">
    <input type="hidden" name="_token" value="{{csrf_token()}}">
	Ou simplesmente crie este campo assim:
	{!! csrf_field() !!}
    ...
</form>

NOTA: O mesmo vale para as rotas POST, PUT e DELETE.

Rotas PUT, PATH ou DELETE:
Para enviar requisições para uma destas rotas precisa especificar o método de envio na requisição, veja este exemplo:

$this->put('usuario/{id}', '[email protected]');

Ao acessar http://sua-app.dev/usuario/2 com o verbo http PUT vai acessar essa rota.

Como espeficar que a requisição é PUT, PATH ou DELETE?
Sim, basta enviar o _method na requisição, veja o exemplo:

<form method="POST" action="/usuario/12">
    <!--Precisa enviar o tokem-->
	{!! csrf_field() !!}

	<!--Espeficica o tipo de envio (verbo http)-->
	<input type="hidden" name="_method" value="PUT">
	//Ou
	{{ method_field('PUT') }}
    ...
</form>

NOTA: Nessa rota nos trabalhamos com parâmetros, mas ainda não se preocupe com isso, mais abaixo adiante mais sobre o assunto.

 

 

 

Rotas math e any:

É possível especificar quais método http uma rota espera, veja este exemplo abaixo que rota “noticias” atende tanto requisições POST, quanto GET.

$this->match(['get', 'post'], '/noticias', '[email protected]');

Também é possível criar rotas para todos os tipos de verbos http:

$this->any('postagens', '[email protected]');

Rotas do tipo de ANY aceita qualquer requisição, não importa se é GET, POST, PUT, PATH ou DELETE.

 

 

Rotas Nomeadas:

O recurso do laravel que permite nomear rotas é extremamente útil.
Vamos ao um exemplo para ficar claro o quanto esse recurso pode ajudar, temos essa rota:

$this->get('contact', '[email protected]');

E estamos utilizando essa rota em diversas partes do projeto, em views:

<a href="{{url('/contact')}}">Contato</a>
Nos controllers:

return redirect('/contact');

Agora por algum motivo precisamos atualizar essa URL para contato, o que fazer?
Neste caso vamos precisar refatorar todo o projeto e pesquisar onde utilizamos a rota com a URL /contact e atualizar para /contato. Muito trabalho!

A solução ideal é nomear as rotas, assim fica mais simples de acessar e facilita a manutenção, veja o mesmo exemplo utilizando rota com nome:

$this->get('contact', '[email protected]')->name('contact');

Utilizar na view:

<a href="{{route('contact')}}">Contato</a>

No controller:

return redirect()->route('contact');

Qual a moral da história agora? Agora sua aplicação está livre para alterar a URL quantas vezes quiser, basta alterar a URL e será aplicado onde está utilizando. Essa é a vantagem de rotas nomeadas, fica mais fácil de alterar algo, e ainda facilita a utilização.

Rota nomeada com parâmetro:

$this->get('post/{id}', '[email protected]')->name('post.show');

Para utilizar essa rota passando o parâmetro basta fazer assim:

route('post.show', 12)

route(“nome rota”, “id dinâmico”)
Resultado: http://sua-app.dev/post/12

Rota nomeada com mais de um parâmetro:

$this->get('modulo/{idModulo}/aula/{id}', '[email protected]')->name('lesson');

Utilizar uma rota nomeada com mais de um parâmetro:

route('lesson', ['idModulo' => 1, 'id' => 5]);

route(“nome rota”, “Array com os parâmetros”)
Resultado: http://sua-app.dev/modulo/1/aula/5

 

 

Grupo de Rotas:

Outro recurso muito interessante de rotas do laravel é criar grupo de rotas para aplicar “regras” em conjunto.
Criando um grupo de rotas:

$this->group([], $callback);

$this->group(“Array de configurações”, $callback);

Prefixo:
Algo muito útil para grupo de rotas é trabalhar com prefixo, imagine que temos uma aplicação que tem duas áreas de acesso, o site e o admin. Todas as rotas de admin ficam dentro de /admin/algumacoisa, poderíamos criar as rotas desta maneira:

$this->get('admin/users', '[email protected]');
$this->get('admin/financeiro', '[email protected]');
$this->get('admin/chamados', '[email protected]');

Podemos utilizar um grupo de rotas com prefixo para facilitar o uso:

$this->group(['prefix' => 'admin'], function(){
	$this->get('users', '[email protected]');
	$this->get('financeiro', '[email protected]');
	$this->get('chamados', '[email protected]');

	//Equivale ao acessar: http://sua-app.dev/admin
	$this->get('/', '[email protected]');
});

Uma das vantagens de fazer assim é que se tiver que atualizar de “admin” para “panel” basta simplesmente alterar o prefixo no grupo de rotas.

Namespace:
Seguindo o mesmo exemplo, que temos diversos controllers, e eles estão em /app/Http/Controllers/Admin/, pode definir o namespace diretamente na definição da rota, algo assim:

$this->get('users', 'Admin\[email protected]');
$this->get('financeiro', 'Admin\[email protected]');
$this->get('chamados', 'Admin\[email protected]');

O mais simples neste caso é definir no grupo de rotas qual é o namespace, exemplo:

$this->group(['prefix' => 'admin', 'namespace' => 'Admin'], function(){
	$this->get('users', '[email protected]');
	$this->get('financeiro', '[email protected]');
	$this->get('chamados', '[email protected]');

	//Equivale ao acessar: http://sua-app.dev/admin
	$this->get('/', '[email protected]');
});

Agora no mesmo grupo de rotas definimos um prefixo para as rotas e ainda definimos qual namespace estão.
NOTA: Se o controller estiver dentro de /app/Http/Controllers/ não precisa especificar o namespace, e se colocar dentro do grupo de rotas com o namespace vai dá erro, porque o controller não será encontrado.

Middleware:
Outro ponto muito interessante de grupo de rotas é definir middlewares em conjunto, ou seja, aplicar um middleware (filtro) em várias rotas de uma vez.
Para o exemplo vamos utilizar o clássico middleware “auth” do laravel que já vem pronto e serve exatamente para permitir acesso a apenas usuários autenticados.
Utilizando middleware em rotas sem o auxilio de grupo de rotas:

$this->get('users', '[email protected]')->middleware(['auth']);
$this->get('financeiro', '[email protected]')->middleware('auth');
$this->get('chamados', '[email protected]')->middleware('auth');

Neste exemplo definimos que estas rotas passam pelo middleware “auth”, ou seja, apenas pessoas autentiadas podem acessar.
PS. Ao definir uma rota com middleware (filtro) é possível passar qual ou quais middlewares irá passar, veja que pode passar tanto um array com vários middlewares, e também pode passar uma string com apenas um middleware.

O mesmo exemplo utilizando middleware:

$this->group(['prefix' => 'admin', 'namespace' => 'Admin', 'middleware' => 'auth'], function(){
	$this->get('users', '[email protected]');
	$this->get('financeiro', '[email protected]');
	$this->get('chamados', '[email protected]');

	//Equivale ao acessar: http://sua-app.dev/admin
	$this->get('/', '[email protected]');
});

Agora as rotas dentro deste grupo estão passando pelo middleware “auth”.
PS. O parâmetro “middleware” é possível receber um array com várias middlewares, exemplo:

$this->group(['middleware' => ['auth', 'auth.basic']], $callback);

 

 

Route resource:

$this->resource($uri, $controller);

Quando utilizamos uma rota do tipo resource() isso facilita muito, porque assim você trabalha com padrões de requisições em aplicações web e ainda economiza códigos, porque essa implementação já cria várias rotas automáticas para você.

Exemplo de rota resource:

$this->resource('url', 'NomeController');

Sem resource deveria ter que fazer tudo isso:

$this->get('url', '[email protected]')->name('url.index');
$this->get('url/create', '[email protected]')->name('url.create');
$this->post('url', '[email protected]')->name('url.store');
$this->get('url/{id}', '[email protected]')->name('url.show');
$this->get('url/{id}/edit', '[email protected]')->name('url.edit');
$this->put('url/{id}', '[email protected]')->name('url.update');
$this->delete('url/{id}', '[email protected]')->name('url.destroy');

Notou a diferença?
O simples fato de criar uma rota como resource já economiza muitas linhas de códigos, e ainda nos “obriga” a trabalhar com padrões de requisição (verbos https), sendo GET para visualizar algo, POST para salvar, PUT ou PATH para alterar e DELETE para deletar.

 

 

 

Route Model Binding:

Este recurso permite criar um objeto automaticamente, sem necessidade de recuperar o item pelo id.
Veja o exemplo sem Route Model Binding:

$this->get('usuario/{id}', function($id) {
	// Recupera o usuário pelo ID, ou dá erro caso não encontrar
	$user = \App\User::findOrFail($id);

	//Retorna os dados do usuário
	return $user;
});

Com o recurso Route Model Binding:

$this->model('usuario/{user}', function($user) {
	//Retorna os dados do usuário
	return $user;
});

Ao acessar http://sua-app.dev/usuario/12 terá o mesmo resultado em ambos os casos, porém no exemplo onde utilizamos Route Model Binding a implementação tem o mesmo resultado porém ficou mais simples.

 

 

 

Utilidades:

Redirect Routes:
Antes da versão 5.5 do laravel para criar um “redirecionador” diretamente em uma rota precisava passar no segundo parâmetro um callback para fazer o redirect para a onde fosse necessário, fazer algo assim:

$this->get('url-anterior', function(){
	return redirect('url-redirecionada');
});

Agora é possível fazer isso utilizando o método redirect(), veja:

$this->redirect('/url-anterior', '/url-redirecionada', 301);

Ao acessar http://sua-app.dev/url-anterior vai redirecionar para http://sua-app.dev/url-redirecionada

View Routes:
Para exibir uma view diretamente ao acessar uma rota precisava fazer algo assim:

$this->get('url-rota', function(){
	//O arquivo de view está em /resources/views/
	return view('nome-arquivo-view');
});

Agora pode fazer apenas assim:

$this->view('url-rota', 'nome-arquivo-view');

Se precisar passar variáveis para a view, pode fazer assim:

$this->view('url-rota', 'nome-arquivo-view', ['usuario' => 'Carlos Ferreira']);

PS. Particularmente não gosto muito de retornar uma view diretamente pela rota, porque isso na minha opnião quebra um pouco o paradigma do MVC, o correto é chamar um controller e ele sim retornar a view.

 

 

 

Rotas com Parâmetros:

É possível criar rotas com parâmetros dinâmicos, ou seja, url que valores mutáveis.
Veja um exemplo de uma rota para exibir os detalhes de um usuário pelo seu id:

$this->get('usuario/{id}', function($id) {
	// Recupera o usuário pelo ID
	$user = \App\User::find($id);

	//Retorna os dados do usuário
	return $user;
});

Neste exemplo a rota /usuario espera um parâmetro que é o ID do usuário, e esta variável pode ser dinâmica, ou seja, receber qualquer valor.
Ao acessar essas URLs vai acessar essa rota:
http://sua-app.dev/usuario/1
http://sua-app.dev/usuario/2
http://sua-app.dev/usuario/3

Outro exemplo, rota com mais de um parâmetro:

$this->get('usuario/{id}/post/{idPost}', function($id, $idPost) {
	// Recupera o usuário pelo ID
	$user = \App\User::find($id);

	//Retorna o id do POST
	return $idPost;
});

Essa rota pode acessar acessada assim:
http://sua-app.dev/usuario/1/post/1
http://sua-app.dev/usuario/1/post/2
http://sua-app.dev/usuario/2/post/3
http://sua-app.dev/usuario/2/post/4
Neste exemplo a rota recebe dois parâmetros dinâmicos. Um rota pode receber quantos parâmetros for necessário, mas lembre-se do bom senso, porque uma URL muito grande é prejudicial ao SEO.

Parâmetros Opicionais:

$this->get('usuario/{id?}', function($id = 'Valor Default') {
	//Retorna o id opicional
	return $id;
});

As rotas dos outros exemplos se não informar o parâmetro dá erro, mas neste caso o parâmetro é opcional, ou seja, o valor pode ou não ser informado.
É importante que o $id recebe algo, porque este será o valor default caso o parâmetro não seja informado.
Exemplo:
http://sua-app.dev/usuario/1
ou
http://sua-app.dev/usuario
No primeiro exemplo o valor do $id será “1”
No segundo exemplo o valor do $id será “Valor Default” e não vai gerar erro.

 

 

Helpers:

$route = Route::current();
$name = Route::currentRouteName();
$action = Route::currentRouteAction();
route();

 

 

NOTA:

É importante que uma rota não retorne algo, e sim envie a responsábilidade para quem tem que fazer, o controller.
O papel da rota é direcionar as requisições de acordo com a url acessada, a responsabilidade de delegar as ações é do controller e não da rota.

 

 

Carlos Ferreira

Sobre o Autor:

Carlos Ferreira

Carlos Ferreira é Analista de Sistemas Experiente, Empreendedor, Fundador da empresa EspecializaTi. Certificações: Comptia Linux +, LPI, Novell Certification.

Todos os direitos reservados © 2021 - EspecializaTi. É proibida a reprodução total ou parcial deste conteúdo.