404 Not Found

404 Not Found


nginx

Explicação Detalhada do Sistema de Rotas do Laravel

Rotas são a "recepção" do Laravel—toda requisição HTTP primeiro passa por aqui antes de ser encaminhada ao método do controlador correspondente.

1. O Que Você Vai Aprender


2. Uma História Real de um Gerente de Produto

(1) Problema: Estruturas de URL Caóticas Causam um Desastre de SEO

Alice projetou mais de 30 páginas para o ShopMetrics, mas a convenção de nomenclatura das URLs era completamente caótica: /shop_view.php?id=5, /admin-users-list e /api/getData estavam todos misturados. O crawler do Google era extremamente ineficiente, e quando os usuários compartilhavam links, a barra de endereços exibia uma sequência de parâmetros com pontos de interrogação. Quando Bob reestruturou o backend e alterou uma única URL, todas as 15 instâncias codificadas no frontend retornaram erros 404.

(2) Soluções para Rotas do Laravel

O roteamento do Laravel usa sintaxe declarativa para definir regras de URL, suportando nomenclatura, agrupamento e restrições de parâmetros; alterações feitas em um local entram em vigor globalmente automaticamente.

PHP
// routes/web.php — Rotas limpas, nomeadas e RESTful
Route::get('/shops/{slug}', [ShopController::class, 'show'])
    ->name('shops.show')
    ->where('slug', '[a-z0-9-]+');

// Gerar URL pelo nome — nunca codifique
$url = route('shops.show', ['slug' => 'alice-store']);
// => /shops/alice-store

(3) Resultado

Alice padronizou as regras de URL do ShopMetrics usando rotas nomeadas, resultando em um aumento de 30% nos rankings de SEO. Quando Bob reestruturou as URLs, precisou apenas atualizar as definições de rota; o route() do frontend gerou automaticamente as novas URLs, resultando em zero erros 404.


3. Rotas Básicas

(1) Rotas por Verbo HTTP

O Laravel fornece um método de rota correspondente para cada verbo HTTP:

PHP
// routes/web.php
Route::get('/shops', [ShopController::class, 'index']);
Route::post('/shops', [ShopController::class, 'store']);
Route::put('/shops/{id}', [ShopController::class, 'update']);
Route::patch('/shops/{id}', [ShopController::class, 'updateStatus']);
Route::delete('/shops/{id}', [ShopController::class, 'destroy']);
Verbo HTTP Finalidade Idempotência Operações Típicas
GET Recuperar Recurso Lista/Detalhes
POST Criar Recurso Adicionar
PUT Atualização Completa Substituir
PATCH Atualização Parcial Alteração de Status
DELETE Excluir Recurso Excluir

(2) Rotas "match" e "any"

PHP
// Corresponder a múltiplos verbos
Route::match(['get', 'post'], '/shops/search', [ShopController::class, 'search']);

// Qualquer verbo
Route::any('/fallback', [FallbackController::class, 'handle']);

(1) ▶ Exemplo: Definições de Rotas Básicas do ShopMetrics

PHP
// routes/web.php
Route::get('/', [HomeController::class, 'index'])->name('home');
Route::get('/about', [AboutController::class, 'index'])->name('about');
Route::get('/pricing', [PricingController::class, 'index'])->name('pricing');
Route::get('/contact', [ContactController::class, 'create'])->name('contact.create');
Route::post('/contact', [ContactController::class, 'store'])->name('contact.store');

Saída:

TEXT
// Execução bem-sucedida

4. Parâmetros e Restrições de Rotas

(1) Parâmetros Obrigatórios

PHP
Route::get('/shops/{id}', [ShopController::class, 'show']);
Route::get('/tenants/{tenant}/shops/{shop}', [ShopController::class, 'showForTenant']);

(2) Parâmetros Opcionais

PHP
Route::get('/reports/{type?}', [ReportController::class, 'index']);
// /reports → type = null
// /reports/sales → type = 'sales'

(3) Expressões Regulares

PHP
// Apenas ID numérico
Route::get('/shops/{id}', [ShopController::class, 'show'])
    ->where('id', '[0-9]+');

// Formato slug: minúsculas, números, hifens
Route::get('/shops/{slug}', [ShopController::class, 'showBySlug'])
    ->where('slug', '[a-z0-9-]+');

// Múltiplas restrições
Route::get('/tenants/{tenant}/orders/{id}', [OrderController::class, 'show'])
    ->where(['tenant' => '[a-z0-9-]+', 'id' => '[0-9]+']);
Método de Restrição Uso Descrição
where() Expressão regular de parâmetro único Mais flexível
whereNumber() Apenas números Equivalente a where('id', '[0-9]+')
whereAlpha() Apenas letras Equivalente a where('name', '[a-zA-Z]+')
whereAlphaNumeric() Letras + Números Equivalente a where('name', '[a-zA-Z0-9]+')
whereUuid() Formato UUID Validação automática UUID v4

(1) ▶ Exemplo: Rotas do ShopMetrics com Restrições

PHP
// routes/web.php
Route::get('/shops/{id}', [ShopController::class, 'show'])
    ->whereNumber('id');

Route::get('/categories/{slug}', [CategoryController::class, 'show'])
    ->where('slug', '[a-z0-9-]+');

Route::get('/tenants/{tenant}/dashboard', [DashboardController::class, 'index'])
    ->where('tenant', '[a-z0-9-]+');

Saída:

TEXT
// Execução bem-sucedida

5. Grupos de Rotas

O agrupamento de rotas permite que múltiplas rotas compartilhem configurações (middleware, prefixos, namespaces, etc.), evitando duplicação de código.

(1) Agrupamento por Middleware

PHP
Route::middleware(['auth', 'tenant.resolve'])->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index']);
    Route::get('/shops', [ShopController::class, 'index']);
    Route::get('/orders', [OrderController::class, 'index']);
});

(2) Agrupamento por Prefixo

PHP
Route::prefix('admin')->group(function () {
    Route::get('/users', [AdminUserController::class, 'index']);
    Route::get('/settings', [AdminSettingController::class, 'index']);
    // URL completa: /admin/users, /admin/settings
});

(3) Agrupamento por Nome

PHP
Route::name('admin.')->group(function () {
    Route::get('/users', [AdminUserController::class, 'index'])->name('users');
    // Nome da rota: admin.users
});

(4) Combinação e Agrupamento

PHP
Route::prefix('admin')
    ->middleware(['auth', 'admin'])
    ->name('admin.')
    ->group(function () {
        Route::get('/users', [AdminUserController::class, 'index'])->name('users');
        Route::get('/plans', [AdminPlanController::class, 'index'])->name('plans');
        // URL: /admin/users, nome: admin.users
    });

(1) ▶ Exemplo: Grupos de Rotas Multi-tenant do ShopMetrics

PHP
// routes/web.php — Rotas com consciência de tenant
Route::middleware(['auth', 'tenant.resolve'])->prefix('/{tenant}')->group(function () {
    Route::get('/dashboard', [TenantDashboardController::class, 'index'])
        ->name('tenant.dashboard');
    Route::resource('/shops', ShopController::class);
    Route::resource('/orders', OrderController::class);
    Route::resource('/products', ProductController::class);
});

Saída:

TEXT
// Execução bem-sucedida

6. Nomenclatura de Rotas e Geração de URL

(1) Rotas Nomeadas

PHP
Route::get('/shops/{id}', [ShopController::class, 'show'])
    ->name('shops.show');

(2) Gerar uma URL

PHP
// Em templates Blade ou controladores
$url = route('shops.show', ['id' => 5]);
// => http://shopmetrics.test/shops/5

// Com parâmetros de consulta
$url = route('shops.index', ['sort' => 'name', 'page' => 2]);
// => http://shopmetrics.test/shops?sort=name&page=2
Função Finalidade Exemplo
route() Gerar URL de rota nomeada route('shops.show', 5)
url() Gerar URL absoluta url('/shops')
action() Gerar baseado no método do controlador action([ShopController::class, 'show'], 5)

(1) ▶ Exemplo: Usando Rotas Nomeadas no Blade

HTML
<a href="{{ route('shops.show', $shop->id) }}">{{ $shop->name }}</a>

<form action="{{ route('shops.update', $shop->id) }}" method="POST">
    @method('PUT')
    @csrf
    <!-- campos do formulário -->
</form>

Saída:

TEXT
// Execução bem-sucedida

7. Rotas de API

routes/api.php Usado exclusivamente para rotas de API; adiciona automaticamente o prefixo /api.

(1) Rota apiResource

PHP
// routes/api.php
use App\Http\Controllers\Api\ShopController;

Route::apiResource('shops', ShopController::class);
// Gera:
// GET    /api/shops        → index
// POST   /api/shops        → store
// GET    /api/shops/{shop} → show
// PUT    /api/shops/{shop} → update
// DELETE /api/shops/{shop} → destroy
Método apiResource resource
index
create
store
show
edit
update
destroy

(2) Versionamento de API

PHP
Route::prefix('v1')->group(function () {
    Route::apiResource('shops', Api\V1\ShopController::class);
    Route::apiResource('orders', Api\V1\OrderController::class);
});

Route::prefix('v2')->group(function () {
    Route::apiResource('shops', Api\V2\ShopController::class);
});

(1) ▶ Exemplo: Blueprint de Rotas de API do ShopMetrics

PHP
// routes/api.php
Route::middleware('auth:sanctum')->group(function () {
    Route::prefix('v1')->name('api.v1.')->group(function () {
        Route::apiResource('tenants.shops', Api\V1\TenantShopController::class);
        Route::apiResource('shops.orders', Api\V1\ShopOrderController::class);
        Route::apiResource('products', Api\V1\ProductController::class);
        Route::get('analytics/overview', [Api\V1\AnalyticsController::class, 'overview']);
        Route::post('reports/generate', [Api\V1\ReportController::class, 'generate']);
    });
});

Saída:

TEXT
// Execução bem-sucedida

8. Processo de Correspondência de Rotas

100%
flowchart LR
    A[Requisição HTTP] --> B{Rota correspondente?}
    B -->|Sim| C[Extrair Parâmetros]
    C --> D[Executar Middleware]
    D --> E[Chamar Método do Controlador]
    E --> F[Retornar Resposta]
    B -->|Não| G[Rota Fallback]
    G --> H[404 Não Encontrado]

9. Exemplo Completo: Blueprint de Rotas Completo do ShopMetrics

PHP
// ============================================
// Completo: Rotas completas do ShopMetrics
// Abrange: rotas web, rotas api, grupos, restrições
// ============================================

// routes/web.php
Route::get('/', [HomeController::class, 'index'])->name('home');
Route::get('/pricing', [PricingController::class, 'index'])->name('pricing');

Route::middleware('auth')->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
    Route::resource('shops', ShopController::class)->whereNumber('shop');
    Route::resource('shops.orders', OrderController::class)->shallow();
    Route::post('/shops/{shop}/logo', [ShopLogoController::class, 'update'])
        ->name('shops.logo.update');
});

// routes/api.php
Route::prefix('v1')->middleware('auth:sanctum')->group(function () {
    Route::apiResource('shops', Api\ShopController::class);
    Route::apiResource('shops.products', Api\ProductController::class)->shallow();
    Route::apiResource('shops.orders', Api\OrderController::class)->shallow();
    Route::get('analytics/summary', [Api\AnalyticsController::class, 'summary']);
    Route::post('reports/generate', [Api\ReportController::class, 'generate']);
});

❓ Perguntas Frequentes

P Qual é a diferença entre routes/web.php e routes/api.php?
R Rotas em web.php aplicam automaticamente o grupo de middleware web (Session, CSRF, criptografia de cookies), sendo adequado para requisições de páginas; rotas em api.php aplicam automaticamente o grupo de middleware API (limitação de taxa throttle), e as URLs são automaticamente prefixadas com /api, sendo adequado para requisições de API.
P Quando devo usar Route::resource, e quando devo definir rotas manualmente?
R Operações CRUD RESTful podem ser tratadas com uma única linha usando resource/apiResource; para operações não padronizadas (como busca, exportação e operações em lote), defina rotas adicionais manualmente.
P Quais são os benefícios de nomear rotas?
R Nomear rotas desacopla as URLs do código. Para modificar uma URL, basta alterar a definição da rota, e todas as chamadas route() são atualizadas automaticamente. Com URLs codificadas, é necessário fazer uma busca e substituição global a cada alteração, o que facilita perder algumas instâncias.
P O que é uma rota shallow?
R Por padrão, recursos aninhados geram URLs como /shops/{shop}/orders/{order}. A opção "shallow" garante que os sub-recursos sejam aninhados apenas quando um ID é necessário: show, edit, update e delete usam /orders/{order}, enquanto index e create mantêm a estrutura aninhada. Isso reduz a profundidade da URL.
P Ter muitas rotas afeta o desempenho?
R O número de rotas tem muito pouco impacto no desempenho, pois o Laravel usa um algoritmo de correspondência eficiente. No entanto, se você tiver mais de 1.000 rotas, recomendamos armazenar em cache a tabela de rotas usando php artisan route:cache.
P Como visualizar todas as rotas registradas?
R Execute php artisan route:list para listar todas as rotas, incluindo método, URI, nome e middleware. Adicione --path=shops para filtrar rotas por um prefixo específico.

📖 Resumo


📝 Exercícios

  1. Exercício Básico (⭐): Defina as seguintes rotas para o ShopMetrics: Página inicial (GET /), Página Sobre (GET /about) e Página de Contato (GET+POST /contact). Use rotas nomeadas e verifique se estão acessíveis no navegador.

  2. Exercício Avançado (⭐⭐): Use grupos de rotas para projetar um blueprint de rotas da API v1 para o ShopMetrics, incluindo três apiResources—shops, products e orders—junto com middleware de autenticação e o prefixo /api/v1.

  3. Desafio (⭐⭐⭐): Implemente o agrupamento de rotas multi-tenant /{tenant}/*. Escreva um middleware TenantResolve para analisar o tenant a partir da URL e injetá-lo no Request, garantindo que todas as sub-rotas possam recuperar o tenant atual via $request->tenant().

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%