Curso de Laravel
Rutas en Laravel: definir las URLs de tu aplicación
Por Víctor Peña · Publicado el
Hola, ¿cómo están? Empezamos el módulo de la aplicación web. Hoy vemos las rutas: la pieza que decide qué código responde a cada dirección del navegador.
¡Empecemos!
Dónde se definen
En routes/web.php, que como vimos en la lección de estructura es uno de los dos archivos de rutas que trae un proyecto nuevo.
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
Esa ruta dice: cuando alguien visite la raíz del sitio con el método GET, devuelve la vista welcome.
Los métodos HTTP
Route::get('/pacientes', ...); // mostrar
Route::post('/pacientes', ...); // crear
Route::put('/pacientes/{id}', ...); // actualizar completo
Route::patch('/pacientes/{id}', ...); // actualizar parcial
Route::delete('/pacientes/{id}', ...); // eliminar
Cada método tiene un significado convenido, el mismo que vimos al hablar de APIs REST. Respetarlo hace que tu aplicación sea predecible.
Si una ruta debe responder a varios métodos:
Route::match(['get', 'post'], '/buscar', ...);
Route::any('/webhook', ...);
Apuntar a un controlador
Definir la lógica dentro de la ruta sirve para ejemplos, pero en un proyecto real apunta a un controlador:
use App\Http\Controllers\PacienteController;
Route::get('/pacientes', [PacienteController::class, 'index']);
Route::get('/pacientes/{id}', [PacienteController::class, 'show']);
Lo vemos en detalle en la siguiente lección.
Parámetros
Route::get('/pacientes/{id}', function ($id) {
return "Paciente número: $id";
});
El nombre entre llaves llega como argumento.
Parámetros opcionales, con signo de interrogación y valor por defecto:
Route::get('/citas/{estado?}', function ($estado = 'programada') {
return Cita::where('estado', $estado)->get();
});
Restricciones, para que la ruta solo acepte cierto formato:
Route::get('/pacientes/{id}', ...)->whereNumber('id');
Route::get('/perfil/{nombre}', ...)->whereAlpha('nombre');
Route::get('/citas/{estado}', ...)
->whereIn('estado', ['programada', 'atendida', 'cancelada']);
Esto importa más de lo que parece: sin restricción, /pacientes/abc entra en la ruta y falla dentro del controlador. Con whereNumber(), Laravel devuelve un 404 limpio.
Vinculación de modelos
Aquí hay algo muy cómodo que conviene adoptar desde el principio.
// Sin vinculación
Route::get('/pacientes/{id}', function ($id) {
$paciente = Paciente::findOrFail($id);
return view('pacientes.show', compact('paciente'));
});
// Con vinculación
Route::get('/pacientes/{paciente}', function (Paciente $paciente) {
return view('pacientes.show', compact('paciente'));
});
Laravel ve que el parámetro se llama {paciente} y que la función espera un Paciente, así que busca el registro por su id y lo inyecta ya resuelto. Si no existe, devuelve 404 automáticamente.
Y si prefieres buscar por otra columna:
Route::get('/pacientes/{paciente:cedula}', ...);
Rutas con nombre
Esta es de las prácticas que más problemas evita a largo plazo.
Route::get('/pacientes', [PacienteController::class, 'index'])
->name('pacientes.index');
Route::get('/pacientes/{paciente}', [PacienteController::class, 'show'])
->name('pacientes.show');
Y a partir de ahí, en vez de escribir la URL a mano:
route('pacientes.index');
route('pacientes.show', $paciente);
route('pacientes.show', ['paciente' => 5]);
En las vistas:
<a href="{{ route('pacientes.index') }}">Ver pacientes</a>
Por qué importa: el día que decidas cambiar /pacientes por /clientes, lo cambias en la ruta y todos los enlaces del proyecto siguen funcionando. Si escribiste las URLs a mano, te toca buscarlas una por una.
La convención de nombres es recurso.accion: pacientes.index, citas.create, doctores.edit.
Redirecciones y vistas directas
Para casos simples no hace falta controlador:
Route::redirect('/inicio', '/');
Route::redirect('/viejo', '/nuevo', 301); // permanente
Route::view('/nosotros', 'paginas.nosotros');
Route::view('/contacto', 'paginas.contacto', ['telefono' => '76980507']);
Grupos de rutas
Cuando varias rutas comparten algo, se agrupan.
Prefijo común:
Route::prefix('admin')->group(function () {
Route::get('/pacientes', ...); // /admin/pacientes
Route::get('/citas', ...); // /admin/citas
});
Prefijo de nombre:
Route::name('admin.')->group(function () {
Route::get('/pacientes', ...)->name('pacientes'); // admin.pacientes
});
Middleware:
Route::middleware('auth')->group(function () {
Route::get('/panel', ...);
Route::get('/perfil', ...);
});
Y todo combinado, que es como se ve en un proyecto real:
Route::middleware(['auth', 'verified'])
->prefix('admin')
->name('admin.')
->group(function () {
Route::get('/pacientes', [PacienteController::class, 'index'])
->name('pacientes.index');
Route::get('/citas', [CitaController::class, 'index'])
->name('citas.index');
});
Esas rutas quedan en /admin/pacientes, se llaman admin.pacientes.index y exigen usuario autenticado y verificado.
Rutas de recurso
Un CRUD necesita siempre las mismas siete rutas. Laravel las genera de una vez:
Route::resource('pacientes', PacienteController::class);
Eso crea:
| Método | URI | Acción | Nombre |
|---|---|---|---|
| GET | /pacientes |
index | pacientes.index |
| GET | /pacientes/create |
create | pacientes.create |
| POST | /pacientes |
store | pacientes.store |
| GET | /pacientes/{paciente} |
show | pacientes.show |
| GET | /pacientes/{paciente}/edit |
edit | pacientes.edit |
| PUT/PATCH | /pacientes/{paciente} |
update | pacientes.update |
| DELETE | /pacientes/{paciente} |
destroy | pacientes.destroy |
Es el estándar del framework, y adoptarlo hace que cualquier desarrollador entienda tu proyecto de inmediato.
Y se puede acotar:
Route::resource('pacientes', PacienteController::class)
->only(['index', 'show']);
Route::resource('pacientes', PacienteController::class)
->except(['destroy']);
Para recursos anidados:
Route::resource('pacientes.citas', CitaController::class);
// /pacientes/{paciente}/citas
Construiremos un CRUD completo sobre estas rutas en el módulo siguiente.
Ver las rutas registradas
php artisan route:list
php artisan route:list --path=pacientes
php artisan route:list --name=admin
Cuando una dirección devuelva 404, este es el primer comando que hay que ejecutar. Te dice si la ruta existe, con qué método y qué controlador la atiende.
El orden importa
Laravel evalúa las rutas de arriba abajo y usa la primera que coincide:
// Mal: /pacientes/create entra en la primera
Route::get('/pacientes/{id}', ...);
Route::get('/pacientes/create', ...);
// Bien: las rutas fijas van antes que las de parámetro
Route::get('/pacientes/create', ...);
Route::get('/pacientes/{id}', ...);
Es un error que da mensajes confusos, porque la ruta existe pero nunca se alcanza.
Rutas de API
Como vimos, routes/api.php no viene por defecto:
php artisan install:api
Las rutas de ahí llevan automáticamente el prefijo /api, no tienen sesión y se autentican con token. Lo veremos en la lección de API REST.
Errores comunes
- Escribir URLs a mano en lugar de usar
route(). - Rutas con parámetro antes que las fijas.
- No poner restricciones y dejar que el fallo ocurra dentro del controlador.
- Definir lógica en la ruta en lugar de en un controlador.
- Olvidar
install:apiy buscar un archivo que no existe. - No usar
route:listal depurar un 404.
Para cerrar
Las rutas son el mapa de tu aplicación. Dos hábitos que conviene adoptar desde el primer día: ponerles nombre siempre y usar Route::resource para los CRUD.
Con eso, tu proyecto queda predecible y los cambios de URL dejan de ser un problema.
En la siguiente lección vemos los controladores, que es donde va la lógica que estas rutas invocan.
Saludos y éxitos.
Norvic Software
Desarrollamos el software que tu empresa necesita
Somos una empresa de software en Bolivia. Construimos sistemas a medida y aplicaciones móviles, y llevamos Inteligencia Artificial a las empresas que ya tienen un sistema funcionando.
- Software a medida
- Desarrollo web
- Aplicaciones móviles
- Chatbots para WhatsApp
- Agentes de IA
- Integración de IA
- Consultoría técnica
Cotización sin costo · Respuesta directa por WhatsApp