@extends('layouts.docs') @section('title', 'Routing System - OG Framework') @section('body')
Core
API fluente e expressiva para definição de endpoints. Mapeamento de URLs, grupos, middlewares e injeção de dependência automática.
O sistema de rotas é a porta de entrada da aplicação. Mapeia URLs para Controllers, suportando gestão de middleware e validação de parâmetros.
As rotas são definidas na pasta Routes/ de cada módulo:
Ferramentas para acelerar o desenvolvimento e otimizar produção.
# Criar rotas API (Modules/Wmso/Routes/Api.php) ./og make:route Wmso --api # Criar rotas Web ./og make:route Wmso --web # Criar para sub-módulo ./og make:route Workshop/Os --api
Gera a classe com namespace correto e implementa RouterInterface.
# Compilar rotas num único JSON ./og route:cache # Limpar cache (obrigatório após alterações) ./og route:clear # Listar todas as rotas registadas ./og route:list
Crítico: Em produção, o uso do cache evita o processamento pesado de dezenas de ficheiros a cada request.
💡 route:list
O comando ./og route:list mostra todas as rotas com nome, método HTTP, URI, controller e middlewares aplicados. Útil para debugging.
// Definição simples com Closure
Route::get('/status', function () {
return 'Sistema Operacional';
});
// Suporte para todos os verbos HTTP
Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
// Múltiplos verbos numa única rota
Route::match(['get', 'post'], '/analytics', [AnalyticsController::class, 'track']);
// Aceitar qualquer verbo HTTP
Route::any('/webhook', [WebhookController::class, 'handle']);
O RouterDispatcher resolve automaticamente qualquer classe tipada na assinatura da função ou método do controller.
use Og\Modules\Sales\Services\InvoiceService;
Route::get('/invoice/{id}', function (InvoiceService $service, $id) {
return $service->download($id);
});
Capture segmentos da URI definindo parâmetros entre chavetas {}.
Route::get('/user/{id}', function ($id) {
return 'User '.$id;
});
// Múltiplos parâmetros
Route::get('/posts/{post}/comments/{comment}',
function ($postId, $commentId) {
// $postId e $commentId injetados por ordem
}
);
// Obrigatório definir valor default
Route::get('/posts/{page?}', function ($page = 1) {
return "Página: $page";
});
// Múltiplos opcionais
Route::get('/search/{query?}/{limit?}',
function ($query = '', $limit = 10) {
// ...
}
);
Em Closures, a ordem dos argumentos importa (são mapeados pela posição).
Em Controllers, o RouterDispatcher pode mapear por nome ou tipo-hint automaticamente.
Restrinja os valores dos parâmetros usando expressões regulares com ->where().
// Constraint simples - apenas números
Route::get('/user/{id}', [UserController::class, 'show'])
->where('id', '[0-9]+');
// Múltiplos constraints
Route::get('/user/{id}/{name}', [UserController::class, 'profile'])
->where(['id' => '[0-9]+', 'name' => '[a-zA-Z]+']);
// Shortcuts comuns
Route::get('/user/{id}', ...)->whereNumber('id');
Route::get('/user/{name}', ...)->whereAlpha('name');
Route::get('/user/{slug}', ...)->whereAlphaNumeric('slug');
Route::get('/category/{uuid}', ...)->whereUuid('uuid');
Definir padrões globais no RouteServiceProvider:
// Em boot()
Route::pattern('id', '[0-9]+');
Route::pattern('uuid', '[a-f0-9-]{36}');
PHP valida o tipo automaticamente:
Route::get('/user/{id}', function (int $id) {
// Se {id} não for int, erro lançado
return User::find($id);
});
Route::get('/user/profile', [ProfileController::class, 'show'])
->name('profile.show');
// Gerar URL pelo nome
$url = route('profile.show');
// Redirecionar para rota nomeada
return redirect()->route('profile.show');
Use sempre pontos para separar contexto, módulo e ação. Exemplo: api.wmso.articles.show.
Contexto
Módulo
Recurso.Ação
O helper route() gera URLs baseadas nos nomes das rotas, garantindo flexibilidade e evitando hardcoding.
// URL simples
$url = route('profile.show');
// → http://app.com/user/profile
// Com parâmetros
$url = route('user.show', ['id' => 123]);
// → http://app.com/user/123
// Múltiplos parâmetros
$url = route('post.comment', ['post' => 1, 'comment' => 5]);
// → http://app.com/posts/1/comments/5
// Parâmetros extras → query string
$url = route('user.index', ['page' => 2, 'sort' => 'name']);
// → http://app.com/users?page=2&sort=name
<a href="@{{ route('profile.show') }}">
Ver Perfil
</a>
<form action="@{{ route('user.update', $user) }}">
...
</form>
// URL absoluta (padrão)
route('home');
// → http://app.com/
// Path relativo
route('home', [], false);
// → /
Evite repetição agrupando rotas com prefixos, middlewares ou controllers comuns.
Route::name('admin.')
->prefix('admin')
->middleware('auth')
->group(function () {
Route::get('/users', 'Users@index')
->name('users');
// URL: /admin/users
// Nome: admin.users
});
Route::controller(OrderController::class)
->group(function () {
Route::get('/orders', 'index');
Route::post('/orders', 'store');
Route::get('/orders/{id}', 'show');
Route::put('/orders/{id}', 'update');
Route::delete('/orders/{id}', 'destroy');
});
// Exemplo real: API do módulo WMSO
Route::name('api.')
->prefix('api')
->middleware(['api', 'throttle:60,1'])
->group(function () {
Route::name('wmso.')
->prefix('wmso')
->group(function () {
Route::name('articles.')
->controller(ArticleController::class)
->group(function () {
Route::get('/', 'index')->name('index'); // api.wmso.articles.index
Route::get('/{id}', 'show')->name('show'); // api.wmso.articles.show
Route::post('/', 'store')->name('store'); // api.wmso.articles.store
});
});
});
Middlewares filtram e processam requests antes de chegarem ao controller. Podem ser aplicados a rotas individuais ou grupos.
Route::get('/admin', [AdminController::class, 'index'])
->middleware('auth');
// Múltiplos middlewares
Route::get('/dashboard', ...)
->middleware(['auth', 'verified']);
Route::middleware(['auth', 'admin'])
->group(function () {
Route::get('/users', ...);
Route::get('/settings', ...);
});
// Middlewares com parâmetros
// Rate limiting: 60 requests por minuto
Route::middleware('throttle:60,1')->group(...);
// Verificar role específica
Route::middleware('role:admin')->group(...);
// Excluir middleware específico
Route::withoutMiddleware('csrf')->post('/webhook', ...);
| Middleware | Descrição |
|---|---|
| auth | Requer autenticação |
| guest | Apenas visitantes (não autenticados) |
| throttle:X,Y | Rate limit (X requests por Y minutos) |
| verified | Email verificado |
| signed | URL com assinatura válida |
Shortcuts para casos comuns que não precisam de controller.
// Redirect 302 (temporário)
Route::redirect('/here', '/there');
// Redirect 301 (permanente)
Route::permanentRedirect(
'/old',
'/new'
);
// Renderizar view diretamente
Route::view('/about', 'pages.about');
// Com dados
Route::view('/terms', 'legal.terms', [
'version' => '2.1'
]);
// 404 customizado
Route::fallback(function () {
return response()
->view('errors.404')
->setStatusCode(404);
});
O trait RouteHelper no Request permite verificar onde estamos e aceder a parâmetros da rota.
Verifica nome da rota (suporta wildcards).
if ($req->routeIs('admin.*')) { }
if ($req->routeIs('*.store')) { }
Verifica URL (path).
if ($req->is('api/v1/*')) { }
Obtém valor de parâmetro.
$id = $req->route('id');
// URL: /api/wmso/articles/10?page=2
// Path sem query string
$request->path(); // "api/wmso/articles/10"
// URL completa
$request->url(); // "http://domain.com/api/wmso/articles/10"
// URL com query string
$request->fullUrl(); // "http://domain.com/api/wmso/articles/10?page=2"
// Segmentos da URL (array)
$request->segments(); // ['api', 'wmso', 'articles', '10']
// Segmento específico (1-based index)
$request->segment(2); // 'wmso'
$request->segment(4); // '10'
// Todos os parâmetros da rota
$request->routeParameters(); // ['id' => '10']
Formulários HTML não suportam PUT, PATCH ou DELETE nativamente. Use a diretiva @@method().
<form action="/users/1" method="POST">
@@method('PUT')
@@csrf
<!-- campos do formulário -->
</form>
<!-- Para DELETE -->
<form action="/users/1" method="POST">
@@method('DELETE')
@@csrf
<button type="submit">Eliminar</button>
</form>
Verifique se definiu o ->name(). Lembre-se que em grupos, os prefixos concatenam-se. Use ./og route:list para confirmar os nomes finais.
Se $request->route('id') for null, certifique-se que a rota tem {id}. Query strings (?id=1) usam $request->input('id').
Após alterar rotas em produção, execute ./og route:clear && ./og route:cache. O cache antigo não reflete as novas alterações.
Para ver todas as rotas registadas: dd(RouterCollector::getInstance()->getRoutes()) ou use ./og route:list.
route() em vez de URLs hardcodedroute:cache em produçãoindex sem prefixo| Método/Helper | Descrição | Exemplo |
|---|---|---|
| Route::get/post/put/... | Definir rota com verbo HTTP | Route::get('/users', ...) |
| ->name() | Atribuir nome à rota | ->name('users.index') |
| ->where() | Constraint regex | ->where('id', '[0-9]+') |
| ->middleware() | Aplicar middleware | ->middleware('auth') |
| route($name, $params) | Gerar URL por nome | route('user.show', ['id' => 1]) |
| $req->routeIs() | Verificar nome da rota | $req->routeIs('admin.*') |
| $req->route($param) | Obter parâmetro da rota | $req->route('id') |
| $req->segment($n) | Segmento N da URL (1-based) | $req->segment(2) |