9: Enrutamiento Básico en Laravel 12 - Guía Práctica
Introducción
El enrutamiento es uno de los pilares fundamentales de cualquier aplicación web. En Laravel, el sistema de rutas es elegante, poderoso y flexible, permitiéndote definir cómo tu aplicación responde a las diferentes peticiones HTTP. En este tutorial, aprenderás desde los conceptos más básicos hasta técnicas avanzadas de enrutamiento en Laravel 12.
Índice
¿Qué es el Enrutamiento?
Estructura de Rutas en Laravel
Tipos de Rutas por Método HTTP
Rutas con Parámetros
Rutas con Expresiones Regulares
Nombres de Rutas
Grupos de Rutas
Rutas Resource
Redirecciones y Vistas
Rutas para API
Ejercicio Práctico: Sistema de Pasteles
1. ¿Qué es el Enrutamiento?
El enrutamiento es el proceso mediante el cual tu aplicación determina qué código ejecutar cuando un usuario accede a una URL específica. Laravel utiliza un sistema de rutas que mapea las URLs a controladores o funciones anónimas (closures).
Flujo básico de una petición HTTP en Laravel
Usuario (Navegador)
↓
Petición HTTP (GET /pasteles)
↓
Archivo routes/web.php
↓
Coincidencia de ruta
↓
Controlador/Closure
↓
Vista/Respuesta
↓
Usuario ve la páginaArquitectura MVC en Laravel
┌─────────────────────────────────────────────────────────────┐
│ USUARIO │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ RUTAS (routes) │
│ app/Http/routes.php │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ CONTROLADORES │
│ app/Http/Controllers/ │
└──────────┬──────────────────────────────────┬──────────────┘
│ │
▼ ▼
┌─────────────────────┐ ┌─────────────────────────────┐
│ MODELOS │ │ VISTAS │
│ app/Models/ │ │ resources/views/ │
│ (Base de Datos) │ │ (HTML con Blade) │
└─────────────────────┘ └─────────────────────────────┘2. Estructura de Rutas en Laravel
Archivos de Rutas
Laravel 12 organiza las rutas en varios archivos dentro de la carpeta routes/:
routes/
├── web.php # Rutas para la interfaz web (sesiones, CSRF, etc.)
├── api.php # Rutas para API (sin sesiones, con tokens)
├── console.php # Rutas para comandos de consola
└── channels.php # Rutas para canales de broadcastingRuta básica
// routes/web.php
use Illuminate\Support\Facades\Route;
// Ruta más simple: devuelve texto
Route::get('/saludo', function () {
return "Bienvenido a Laravel 12!";
});Ruta con vista
// Ruta que devuelve una vista
Route::get('/inicio', function () {
return view('inicio');
});
// Ruta que devuelve una vista con datos
Route::get('/pasteles', function () {
$titulo = "Lista de Pasteles";
return view('pasteles.index', ['titulo' => $titulo]);
});Ruta que usa un controlador
// Usando el formato tradicional
Route::get('/pasteles', [PastelController::class, 'index']);
// Usando el formato de invocación (Laravel 12)
Route::get('/pasteles', 'App\Http\Controllers\PastelController@index');
// Con el namespace completo (Laravel 12)
Route::get('/pasteles', 'PastelController@index');3. Tipos de Rutas por Método HTTP
Verbos HTTP disponibles
| Método | Uso | Ejemplo |
|---|---|---|
| GET | Obtener recursos | Mostrar página, listar datos |
| POST | Crear recursos | Enviar formulario, crear registro |
| PUT | Actualizar recursos | Actualizar completamente |
| PATCH | Actualizar parcialmente | Modificar algunos campos |
| DELETE | Eliminar recursos | Borrar registro |
| OPTIONS | Obtener opciones | CORS preflight |
Ejemplos de cada tipo
use Illuminate\Http\Request;
// GET - Obtener lista de pasteles
Route::get('/pasteles', function () {
return "Lista de pasteles";
});
// POST - Crear un nuevo pastel
Route::post('/pasteles', function (Request $request) {
return "Creando un pastel: " . $request->nombre;
});
// PUT - Actualizar un pastel completamente
Route::put('/pasteles/{id}', function ($id) {
return "Actualizando pastel ID: " . $id;
});
// PATCH - Actualizar parcialmente un pastel
Route::patch('/pasteles/{id}', function ($id) {
return "Actualizando parcialmente pastel ID: " . $id;
});
// DELETE - Eliminar un pastel
Route::delete('/pasteles/{id}', function ($id) {
return "Eliminando pastel ID: " . $id;
});
// Ruta que acepta cualquier método HTTP
Route::any('/cualquiera', function () {
return "Esta ruta acepta cualquier método HTTP";
});
// Ruta que coincide con múltiples verbos
Route::match(['get', 'post'], '/mixta', function () {
return "Esta ruta acepta GET y POST";
});Verificar las rutas registradas
# Listar todas las rutas
php artisan route:list
# Filtrar por nombre
php artisan route:list --name=pasteles
# Filtrar por método
php artisan route:list --method=POST
# Ver rutas en formato JSON
php artisan route:list --json4. Rutas con Parámetros
Parámetros obligatorios
// Parámetro simple
Route::get('/pastel/{id}', function ($id) {
return "Mostrando pastel con ID: " . $id;
});
// Múltiples parámetros
Route::get('/pastel/{id}/ingrediente/{ingredienteId}', function ($id, $ingredienteId) {
return "Pastel ID: {$id}, Ingrediente ID: {$ingredienteId}";
});
// Parámetros con nombres descriptivos
Route::get('/usuario/{nombre}/pastel/{pastelId}', function ($nombre, $pastelId) {
return "Usuario: {$nombre} - Pastel: {$pastelId}";
});Parámetros opcionales
// Parámetro opcional (con ? y valor por defecto)
Route::get('/pasteles/{sabor?}', function ($sabor = 'todos') {
return "Mostrando pasteles de sabor: " . $sabor;
});
// Múltiples parámetros opcionales
Route::get('/buscar/{categoria?}/{subcategoria?}', function ($categoria = 'todos', $subcategoria = null) {
return "Buscando: Categoría: {$categoria}, Subcategoría: {$subcategoria}";
});
// Parámetro opcional con validación adicional
Route::get('/pasteles/{sabor?}', function ($sabor = 'todos') {
$saboresValidos = ['chocolate', 'vainilla', 'cheesecake', 'todos'];
if (!in_array($sabor, $saboresValidos)) {
return "Sabor no válido";
}
return "Mostrando pasteles de sabor: " . $sabor;
});Parámetros con nombres y validación
// Parámetros con nombres claros
Route::get('/pasteles/{nombre}/{sabor}', function ($nombre, $sabor) {
return "Pastel: {$nombre}, Sabor: {$sabor}";
});
// Parámetros con tipado
Route::get('/pasteles/{id}', function (int $id) {
return "Pastel con ID numérico: " . $id;
});
// Parámetros con validación de tipo
Route::get('/pasteles/{id}', function (string $id) {
return "ID como string: " . $id;
});5. Rutas con Expresiones Regulares
Validación con where
// Validar que el ID sea numérico
Route::get('/pastel/{id}', function ($id) {
return "Pastel ID: " . $id;
})->where('id', '[0-9]+');
// Validar que el nombre solo tenga letras
Route::get('/pastel/nombre/{nombre}', function ($nombre) {
return "Pastel: " . $nombre;
})->where('nombre', '[A-Za-zÁ-ú]+');
// Validar formato específico
Route::get('/pastel/codigo/{codigo}', function ($codigo) {
return "Código: " . $codigo;
})->where('codigo', '[A-Z]{3}-[0-9]{4}');
// Múltiples restricciones
Route::get('/pastel/{id}/{nombre}', function ($id, $nombre) {
return "ID: {$id}, Nombre: {$nombre}";
})->where([
'id' => '[0-9]+',
'nombre' => '[A-Za-zÁ-ú\s]+'
]);
// Restricción de longitud
Route::get('/pastel/{codigo}', function ($codigo) {
return "Código: " . $codigo;
})->where('codigo', '^[A-Za-z0-9]{8}$');Patrones comunes con expresiones regulares
// ID numérico
Route::get('/usuario/{id}', function ($id) {
return "Usuario ID: " . $id;
})->where('id', '[0-9]+');
// UUID
Route::get('/pedido/{uuid}', function ($uuid) {
return "Pedido UUID: " . $uuid;
})->where('uuid', '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}');
// Email
Route::get('/usuario/email/{email}', function ($email) {
return "Email: " . $email;
})->where('email', '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}');
// Fecha (YYYY-MM-DD)
Route::get('/reporte/{fecha}', function ($fecha) {
return "Fecha: " . $fecha;
})->where('fecha', '[0-9]{4}-[0-9]{2}-[0-9]{2}');
// Teléfono (10 dígitos)
Route::get('/telefono/{numero}', function ($numero) {
return "Teléfono: " . $numero;
})->where('numero', '^[0-9]{10}$');
// Código postal (México)
Route::get('/codigo-postal/{cp}', function ($cp) {
return "Código Postal: " . $cp;
})->where('cp', '^[0-9]{5}$');
// URL amigable (slug)
Route::get('/articulo/{slug}', function ($slug) {
return "Artículo: " . $slug;
})->where('slug', '[a-z0-9-]+');Parámetros con valores por defecto y restricciones
// Valor por defecto con restricción
Route::get('/pasteles/{sabor?}', function ($sabor = 'todos') {
return "Sabor: " . $sabor;
})->where('sabor', '[a-zA-Z]+');
// Múltiples parámetros con valores por defecto
Route::get('/buscar/{categoria?}/{orden?}', function ($categoria = 'todos', $orden = 'asc') {
return "Categoría: {$categoria}, Orden: {$orden}";
})->where([
'categoria' => '[a-zA-Z]+',
'orden' => 'asc|desc'
]);6. Nombres de Rutas
Asignar nombres a las rutas
// Ruta con nombre básico
Route::get('/pasteles', function () {
return "Lista de pasteles";
})->name('pasteles.index');
// Ruta con nombre y parámetros
Route::get('/pastel/{id}', function ($id) {
return "Pastel ID: " . $id;
})->name('pasteles.show');
// Ruta con nombre y controlador
Route::get('/pasteles/crear', [PastelController::class, 'create'])
->name('pasteles.create');
// Ruta con nombre en el segundo parámetro
Route::get('/pasteles/editar', 'PastelController@edit')->name('pasteles.edit');Generar URLs con nombres de rutas
// En cualquier parte de la aplicación
// Generar URL de la ruta nombrada
$url = route('pasteles.index');
// Resultado: /pasteles
// Generar URL con parámetros
$url = route('pasteles.show', ['id' => 1]);
// Resultado: /pastel/1
// Generar URL con múltiples parámetros
$url = route('pasteles.filtro', ['sabor' => 'chocolate', 'precio' => 'bajo']);
// Resultado: /pasteles/filtro/chocolate/bajo
// En Blade
<a href="{{ route('pasteles.index') }}">Lista de Pasteles</a>
<a href="{{ route('pasteles.show', ['id' => $pastel->id]) }}">Ver Pastel</a>
// Redirección con nombre
return redirect()->route('pasteles.index');
// Redirección con parámetros
return redirect()->route('pasteles.show', ['id' => $pastel->id]);Nombres de rutas con parámetros opcionales
// Ruta con nombre y parámetro opcional
Route::get('/pasteles/{sabor?}', function ($sabor = 'todos') {
return "Sabor: " . $sabor;
})->name('pasteles.por-sabor');
// Generar URL sin parámetro
$url = route('pasteles.por-sabor');
// Resultado: /pasteles
// Generar URL con parámetro
$url = route('pasteles.por-sabor', ['sabor' => 'chocolate']);
// Resultado: /pasteles/chocolateOrganizar nombres con grupos
Route::name('admin.')->group(function () {
Route::get('/admin/dashboard', function () {
return "Dashboard";
})->name('dashboard'); // admin.dashboard
Route::get('/admin/usuarios', function () {
return "Usuarios";
})->name('usuarios'); // admin.usuarios
Route::get('/admin/usuarios/{id}', function ($id) {
return "Usuario: " . $id;
})->name('usuarios.show'); // admin.usuarios.show
});
// Uso
$url = route('admin.dashboard');
$url = route('admin.usuarios');
$url = route('admin.usuarios.show', ['id' => 1]);7. Grupos de Rutas
Grupo básico de rutas
// Agrupar rutas con prefijo
Route::prefix('admin')->group(function () {
Route::get('/dashboard', function () {
return "Dashboard de administración";
});
Route::get('/usuarios', function () {
return "Lista de usuarios";
});
Route::get('/usuarios/{id}', function ($id) {
return "Usuario ID: " . $id;
});
});
// Acceso: /admin/dashboard, /admin/usuarios, /admin/usuarios/1Grupo con prefijo y nombre
Route::prefix('admin')
->name('admin.')
->group(function () {
Route::get('/dashboard', function () {
return "Dashboard";
})->name('dashboard'); // admin.dashboard
Route::get('/usuarios', function () {
return "Usuarios";
})->name('usuarios'); // admin.usuarios
});Grupo con middleware
// Grupo con middleware de autenticación
Route::middleware(['auth'])->group(function () {
Route::get('/perfil', function () {
return "Perfil de usuario";
});
Route::get('/configuracion', function () {
return "Configuración";
});
});
// Grupo con múltiples middlewares
Route::middleware(['auth', 'admin'])->group(function () {
Route::get('/admin/dashboard', function () {
return "Dashboard de administrador";
});
Route::get('/admin/usuarios', function () {
return "Gestión de usuarios";
});
});Grupo con prefijo, middleware y nombre
Route::prefix('admin')
->middleware(['auth', 'admin'])
->name('admin.')
->group(function () {
Route::get('/dashboard', function () {
return "Dashboard";
})->name('dashboard');
Route::get('/usuarios', function () {
return "Usuarios";
})->name('usuarios');
});Grupo para rutas de API
Route::prefix('api')
->middleware('api')
->group(function () {
Route::get('/pasteles', function () {
return response()->json(['pasteles' => []]);
});
Route::post('/pasteles', function () {
return response()->json(['mensaje' => 'Creado'], 201);
});
Route::get('/pasteles/{id}', function ($id) {
return response()->json(['pastel' => ['id' => $id]]);
});
});Grupo con subdominio
Route::domain('admin.miapp.com')->group(function () {
Route::get('/dashboard', function () {
return "Dashboard en subdominio admin";
});
Route::get('/reportes', function () {
return "Reportes en subdominio admin";
});
});
// Grupo con subdominio dinámico
Route::domain('{empresa}.miapp.com')->group(function () {
Route::get('/dashboard', function ($empresa) {
return "Dashboard de: " . $empresa;
});
});8. Rutas Resource
Crear una ruta resource
// Ruta resource básica
Route::resource('pasteles', PastelController::class);
// Rutas generadas automáticamente:
// GET /pasteles index
// GET /pasteles/create create
// POST /pasteles store
// GET /pasteles/{pastel} show
// GET /pasteles/{pastel}/edit edit
// PUT/PATCH /pasteles/{pastel} update
// DELETE /pasteles/{pastel} destroyPersonalizar rutas resource
// Solo algunos métodos
Route::resource('pasteles', PastelController::class)
->only(['index', 'show']);
// Excepto algunos métodos
Route::resource('pasteles', PastelController::class)
->except(['create', 'store', 'edit', 'update', 'destroy']);
// Personalizar nombres
Route::resource('pasteles', PastelController::class)
->names([
'index' => 'pasteles.lista',
'create' => 'pasteles.crear',
'store' => 'pasteles.guardar',
'show' => 'pasteles.ver',
'edit' => 'pasteles.editar',
'update' => 'pasteles.actualizar',
'destroy' => 'pasteles.eliminar'
]);
// Personalizar parámetros
Route::resource('pasteles', PastelController::class)
->parameters(['pasteles' => 'pastel_id']);Recursos anidados
// Recursos anidados
Route::resource('categorias.pasteles', PastelController::class)
->shallow();
// Rutas generadas:
// GET /categorias/{categoria}/pasteles index
// GET /categorias/{categoria}/pasteles/create create
// POST /categorias/{categoria}/pasteles store
// GET /pasteles/{pastel} show
// GET /pasteles/{pastel}/edit edit
// PUT/PATCH /pasteles/{pastel} update
// DELETE /pasteles/{pastel} destroyRecursos API
// Rutas resource para API (sin create/edit)
Route::apiResource('pasteles', PastelController::class);
// Rutas API solo con algunos métodos
Route::apiResource('pasteles', PastelController::class)
->only(['index', 'show', 'store', 'update', 'destroy']);
// Rutas API con nombres personalizados
Route::apiResource('pasteles', PastelController::class)
->names([
'index' => 'api.pasteles.lista',
'store' => 'api.pasteles.guardar'
]);9. Redirecciones y Vistas
Redirecciones en rutas
// Redirección simple
Route::redirect('/antigua', '/nueva');
// Redirección con código de estado
Route::redirect('/antigua', '/nueva', 301);
// Redirección con nombre de ruta
Route::permanentRedirect('/antigua', '/nueva');Vistas directas desde rutas
// Vista directa
Route::view('/inicio', 'inicio');
// Vista con datos
Route::view('/bienvenida', 'bienvenida', ['nombre' => 'Juan']);
// Vista con múltiples datos
Route::view('/dashboard', 'dashboard', [
'titulo' => 'Panel de Control',
'usuario' => 'Administrador'
]);
// Vista con datos dinámicos
Route::view('/perfil', 'perfil', [
'nombre' => auth()->user()->name ?? 'Invitado',
'email' => auth()->user()->email ?? 'Sin email'
]);10. Rutas para API
Configuración de rutas API
// routes/api.php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
// Ruta básica de API
Route::get('/pasteles', function () {
return response()->json([
'success' => true,
'data' => [
['id' => 1, 'nombre' => 'Pastel de Chocolate'],
['id' => 2, 'nombre' => 'Pastel de Vainilla']
]
]);
});
// Ruta con parámetros
Route::get('/pasteles/{id}', function ($id) {
return response()->json([
'success' => true,
'data' => ['id' => $id, 'nombre' => 'Pastel de Chocolate']
]);
});
// Ruta POST
Route::post('/pasteles', function (Request $request) {
return response()->json([
'success' => true,
'message' => 'Pastel creado',
'data' => $request->all()
], 201);
});
// Ruta PUT
Route::put('/pasteles/{id}', function ($id, Request $request) {
return response()->json([
'success' => true,
'message' => 'Pastel actualizado',
'data' => ['id' => $id] + $request->all()
]);
});
// Ruta DELETE
Route::delete('/pasteles/{id}', function ($id) {
return response()->json([
'success' => true,
'message' => 'Pastel eliminado',
'data' => ['id' => $id]
]);
});Grupo de rutas API con versión
// routes/api.php
Route::prefix('v1')->group(function () {
Route::get('/pasteles', [Api\PastelController::class, 'index']);
Route::post('/pasteles', [Api\PastelController::class, 'store']);
Route::get('/pasteles/{id}', [Api\PastelController::class, 'show']);
Route::put('/pasteles/{id}', [Api\PastelController::class, 'update']);
Route::delete('/pasteles/{id}', [Api\PastelController::class, 'destroy']);
});
Route::prefix('v2')->group(function () {
Route::get('/pasteles', [Api\V2\PastelController::class, 'index']);
// Versionamiento de API
});Middleware para API
Route::middleware('auth:api')->group(function () {
Route::get('/pasteles', [Api\PastelController::class, 'index']);
Route::post('/pasteles', [Api\PastelController::class, 'store']);
Route::get('/pasteles/{id}', [Api\PastelController::class, 'show']);
});
Route::middleware('throttle:60,1')->group(function () {
Route::get('/publicos', function () {
return response()->json(['publico' => true]);
});
});11. Ejercicio Práctico: Sistema de Pasteles
Paso 1: Crear el archivo de rutas
// routes/web.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PastelController;
/*
|--------------------------------------------------------------------------
| Rutas del Sistema de Pasteles
|--------------------------------------------------------------------------
*/
// Ruta principal del sistema
Route::get('/', function () {
return view('welcome');
})->name('home');
// Grupo de rutas para pasteles
Route::prefix('pasteles')
->name('pasteles.')
->group(function () {
// Ruta para listar todos los pasteles
Route::get('/', [PastelController::class, 'index'])
->name('index');
// Ruta para mostrar formulario de creación
Route::get('/crear', [PastelController::class, 'create'])
->name('create');
// Ruta para guardar un nuevo pastel
Route::post('/', [PastelController::class, 'store'])
->name('store');
// Ruta para mostrar un pastel específico
Route::get('/{pastel}', [PastelController::class, 'show'])
->where('pastel', '[0-9]+')
->name('show');
// Ruta para mostrar formulario de edición
Route::get('/{pastel}/editar', [PastelController::class, 'edit'])
->where('pastel', '[0-9]+')
->name('edit');
// Ruta para actualizar un pastel
Route::put('/{pastel}', [PastelController::class, 'update'])
->where('pastel', '[0-9]+')
->name('update');
// Ruta para eliminar un pastel
Route::delete('/{pastel}', [PastelController::class, 'destroy'])
->where('pastel', '[0-9]+')
->name('destroy');
// Ruta adicional: filtrar por sabor
Route::get('/sabor/{sabor}', [PastelController::class, 'porSabor'])
->where('sabor', 'chocolate|vainilla|cheesecake|fresa|coco')
->name('por-sabor');
// Ruta adicional: pasteles disponibles
Route::get('/disponibles', [PastelController::class, 'disponibles'])
->name('disponibles');
});
// Grupo de rutas para API
Route::prefix('api')
->name('api.')
->group(function () {
Route::get('/pasteles', [PastelController::class, 'apiIndex'])
->name('pasteles.index');
Route::get('/pasteles/{id}', [PastelController::class, 'apiShow'])
->where('id', '[0-9]+')
->name('pasteles.show');
Route::post('/pasteles', [PastelController::class, 'apiStore'])
->name('pasteles.store');
});Paso 2: Crear el controlador
php artisan make:controller PastelController<?php
namespace App\Http\Controllers;
use App\Models\Pastel;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\JsonResponse;
class PastelController extends Controller
{
/**
* Listar todos los pasteles
*/
public function index(): View
{
$pasteles = Pastel::all();
return view('pasteles.index', compact('pasteles'));
}
/**
* Mostrar formulario de creación
*/
public function create(): View
{
return view('pasteles.create');
}
/**
* Guardar un nuevo pastel
*/
public function store(Request $request): RedirectResponse
{
$validated = $request->validate([
'nombre' => 'required|string|max:100',
'sabor' => 'required|string|in:chocolate,vainilla,cheesecake,fresa,coco',
'precio' => 'nullable|numeric|min:0',
'disponible' => 'boolean',
'descripcion' => 'nullable|string'
]);
Pastel::create($validated);
return redirect()
->route('pasteles.index')
->with('success', 'Pastel creado exitosamente');
}
/**
* Mostrar un pastel específico
*/
public function show(int $id): View
{
$pastel = Pastel::findOrFail($id);
return view('pasteles.show', compact('pastel'));
}
/**
* Mostrar formulario de edición
*/
public function edit(int $id): View
{
$pastel = Pastel::findOrFail($id);
return view('pasteles.edit', compact('pastel'));
}
/**
* Actualizar un pastel
*/
public function update(Request $request, int $id): RedirectResponse
{
$validated = $request->validate([
'nombre' => 'required|string|max:100',
'sabor' => 'required|string|in:chocolate,vainilla,cheesecake,fresa,coco',
'precio' => 'nullable|numeric|min:0',
'disponible' => 'boolean',
'descripcion' => 'nullable|string'
]);
$pastel = Pastel::findOrFail($id);
$pastel->update($validated);
return redirect()
->route('pasteles.index')
->with('success', 'Pastel actualizado exitosamente');
}
/**
* Eliminar un pastel
*/
public function destroy(int $id): RedirectResponse
{
$pastel = Pastel::findOrFail($id);
$pastel->delete();
return redirect()
->route('pasteles.index')
->with('success', 'Pastel eliminado exitosamente');
}
/**
* Filtrar pasteles por sabor
*/
public function porSabor(string $sabor): View
{
$pasteles = Pastel::where('sabor', $sabor)->get();
return view('pasteles.index', compact('pasteles'));
}
/**
* Mostrar solo pasteles disponibles
*/
public function disponibles(): View
{
$pasteles = Pastel::where('disponible', true)->get();
return view('pasteles.index', compact('pasteles'));
}
/**
* API: Listar pasteles
*/
public function apiIndex(): JsonResponse
{
$pasteles = Pastel::all();
return response()->json([
'success' => true,
'data' => $pasteles
]);
}
/**
* API: Mostrar pastel específico
*/
public function apiShow(int $id): JsonResponse
{
$pastel = Pastel::find($id);
if (!$pastel) {
return response()->json([
'success' => false,
'message' => 'Pastel no encontrado'
], 404);
}
return response()->json([
'success' => true,
'data' => $pastel
]);
}
/**
* API: Crear pastel
*/
public function apiStore(Request $request): JsonResponse
{
$validated = $request->validate([
'nombre' => 'required|string|max:100',
'sabor' => 'required|string|in:chocolate,vainilla,cheesecake,fresa,coco',
'precio' => 'nullable|numeric|min:0',
'disponible' => 'boolean',
'descripcion' => 'nullable|string'
]);
$pastel = Pastel::create($validated);
return response()->json([
'success' => true,
'message' => 'Pastel creado exitosamente',
'data' => $pastel
], 201);
}
}Paso 3: Verificar las rutas
# Ver todas las rutas
php artisan route:list
# Ver rutas del sistema de pasteles
php artisan route:list --path=pasteles
# Ver rutas API
php artisan route:list --path=apiPaso 4: Usar las rutas en Blade
<!-- En una vista Blade -->
<!-- Enlaces usando nombres de rutas -->
<a href="{{ route('pasteles.index') }}">Lista de Pasteles</a>
<a href="{{ route('pasteles.create') }}">Crear Pastel</a>
<a href="{{ route('pasteles.show', ['pastel' => $pastel->id]) }}">Ver Pastel</a>
<a href="{{ route('pasteles.edit', ['pastel' => $pastel->id]) }}">Editar Pastel</a>
<!-- Enlaces con parámetros -->
<a href="{{ route('pasteles.por-sabor', ['sabor' => 'chocolate']) }}">Pasteles de Chocolate</a>
<a href="{{ route('pasteles.disponibles') }}">Pasteles Disponibles</a>
<!-- Formularios con rutas -->
<form action="{{ route('pasteles.store') }}" method="POST">
@csrf
<!-- Campos del formulario -->
</form>
<form action="{{ route('pasteles.update', ['pastel' => $pastel->id]) }}" method="POST">
@csrf
@method('PUT')
<!-- Campos del formulario -->
</form>
<form action="{{ route('pasteles.destroy', ['pastel' => $pastel->id]) }}" method="POST">
@csrf
@method('DELETE')
<button type="submit">Eliminar</button>
</form>Paso 5: Probar las rutas
// Desde el navegador:
// GET /pasteles - Lista de pasteles
// GET /pasteles/crear - Formulario de creación
// POST /pasteles - Guardar pastel
// GET /pasteles/1 - Ver pastel ID 1
// GET /pasteles/1/editar - Editar pastel ID 1
// PUT /pasteles/1 - Actualizar pastel ID 1
// DELETE /pasteles/1 - Eliminar pastel ID 1
// GET /pasteles/sabor/chocolate - Pasteles de chocolate
// GET /pasteles/disponibles - Pasteles disponibles
// Desde API:
// GET /api/pasteles - Listar pasteles (JSON)
// GET /api/pasteles/1 - Ver pastel ID 1 (JSON)
// POST /api/pasteles - Crear pastel (JSON)Comandos Útiles
# Ver todas las rutas registradas
php artisan route:list
# Ver rutas con detalles
php artisan route:list -v
# Ver rutas en formato JSON
php artisan route:list --json
# Filtrar rutas por nombre
php artisan route:list --name=users
# Filtrar rutas por método
php artisan route:list --method=POST
# Filtrar rutas por path
php artisan route:list --path=admin
# Filtrar rutas por dominio
php artisan route:list --domain=admin
# Limpiar caché de rutas
php artisan route:clear
# Generar caché de rutas (producción)
php artisan route:cacheResumen
| Concepto | Descripción | Ejemplo |
|---|---|---|
| Ruta básica | Define una URL y su respuesta | Route::get('/ruta', fn() => 'Hola') |
| Parámetros | Captura valores de la URL | Route::get('/{id}', fn($id) => $id) |
| Parámetros opcionales | Parámetros con valor por defecto | Route::get('/{id?}', fn($id=1) => $id) |
| Expresiones regulares | Valida el formato de parámetros | ->where('id', '[0-9]+') |
| Nombres de rutas | Asigna nombre para referencia | ->name('ruta.nombre') |
| Grupos de rutas | Agrupa rutas con prefijo/middleware | Route::prefix('admin')->group(...) |
| Resource | Genera rutas CRUD automáticamente | Route::resource('pasteles', Controller::class) |
| Redirecciones | Redirige de una URL a otra | Route::redirect('/vieja', '/nueva') |
| Vistas directas | Devuelve una vista sin controlador | Route::view('/ruta', 'vista') |
¡Con este conocimiento, puedes crear un sistema de enrutamiento robusto y bien organizado en Laravel 12
Comentarios
Publicar un comentario