Capítulo 2 de 9

Tutorial Laravel 13 #2: el enrutamiento y las rutas con nombre

verificado el 7 septiembre 2026 · 5 min

Respuesta rápida

Las rutas se declaran en routes/web.php con Route::get('/chemin', [MonController::class, 'methode']). Ponles nombre con ->name() para construir tus enlaces mediante route('nom') en lugar de escribirlos a mano. La sintaxis en cadena 'Controller@methode' ya no funciona desde Laravel 8.

Al final de este capítulo, sabrás asociar una dirección a un controlador, leer un parámetro de URL, dar nombre a una ruta y dejar que Laravel cargue un modelo por ti.

Una ruta asocia una dirección a un trozo de código. Es la puerta de entrada de cualquier petición: Laravel lee la URL solicitada, busca la ruta que le corresponde y ejecuta aquello que designa. Este capítulo repasa las cuatro formas que adopta esa asociación.

La ruta más simple

Todas las rutas del sitio público se declaran en routes/web.php. Este es su contenido recién instalado:

routes/web.php
<?php

use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    return view('welcome');
});

Esa ruta dice: cuando alguien pide / con el método GET, devuelve la vista welcome, es decir, el archivo resources/views/welcome.blade.php.

Route::get() recibe dos argumentos: la dirección y lo que hay que hacer. Este segundo argumento admite varias formas.

Devolver una cadena

routes/web.php
Route::get('/bonjour', function () {
    return 'Bonjour !';
});

Visita http://127.0.0.1:8000/bonjour: el navegador muestra el texto tal cual. Sirve para comprobar que una ruta se alcanza de verdad, y poco más.

Devolver una vista

Para comprobar que welcome es realmente la vista que aparece en la portada, abre resources/views/welcome.blade.php y añade una línea visible en cualquier punto del <body>:

resources/views/welcome.blade.php
<h1>Bonjour tout le monde !</h1>

Recarga la portada: el título aparece. Acabas de modificar una vista sin tocar la ruta.

Devolver un controlador

En un proyecto real, la lógica no vive en el archivo de rutas sino en un controlador. La ruta se limita entonces a señalar una clase y un método:

routes/web.php
use App\Http\Controllers\PostController;

Route::get('/article', [PostController::class, 'show']);

El array [PostController::class, 'show'] significa «llama al método show de la clase PostController». El controlador todavía no existe: lo crea el capítulo siguiente. Fíjate en el use de la cabecera del archivo, que importa la clase. Sin él, PHP buscará PostController en el espacio de nombres global y no lo encontrará.

La sintaxis en cadena ya no existe

Muchos tutoriales escritos para Laravel 7 o versiones anteriores usan Route::get('/article', 'PostController@show'). El prefijo automático de espacio de nombres que hacía posible esa forma se retiró en Laravel 8. En Laravel 13 falla con este mensaje:

code
Illuminate\Contracts\Container\BindingResolutionException
Target class [PostController] does not exist.

Laravel busca la clase en la raíz del espacio de nombres en lugar de en App\Http\Controllers. Usa siempre la forma con array.

Los parámetros de URL

Un blog necesita direcciones variables: /article/mon-premier-article, /article/un-autre. La parte que cambia se convierte en un parámetro, escrito entre llaves:

routes/web.php
Route::get('/article/{slug}', function (string $slug) {
    return "Vous avez demandé l'article : {$slug}";
});

Laravel captura todo lo que sigue a /article/ y se lo pasa a la función con el nombre $slug. El nombre del parámetro en la URL y el del argumento tienen que coincidir.

Puedes restringir la forma esperada. Aquí la ruta solo responderá si el identificador es numérico:

routes/web.php
Route::get('/article/{id}', function (int $id) {
    return "Article numéro {$id}";
})->whereNumber('id');

Una URL como /article/bonjour devolverá entonces un error 404, en vez de llegar a tu código con un valor inesperado.

Las rutas con nombre

Dejar las URL hardcodeadas en las plantillas es frágil: el día que renombres /article/ como /blog/, tendrás que localizar enlace por enlace. Dar nombre a la ruta resuelve el problema:

routes/web.php
Route::get('/article/{slug}', [PostController::class, 'show'])->name('post');

A partir de ahí el enlace se construye desde el nombre, nunca desde la dirección:

php
route('post', ['slug' => 'mon-premier-article'])
// http://127.0.0.1:8000/article/mon-premier-article

En una vista Blade queda así:

markup
<a href="http://%20route('post',%20$post)%20">{{ $post->title }}</a>

Cambia la dirección en web.php y todos los enlaces la siguen. Es la forma en que este tutorial construye todos sus enlaces a partir del capítulo 7.

El route model binding

Laravel puede ir más lejos. Si el parámetro lleva el nombre de un modelo, el framework va a buscar el registro por su cuenta:

routes/web.php
use App\Models\Post;

Route::get('/article/{post}', function (Post $post) {
    return $post->title;
});

Laravel lee el segmento de URL, consulta la tabla posts y devuelve un error 404 automáticamente si no hay coincidencia. Recibes el objeto directamente, sin escribir la consulta. Por defecto la búsqueda se hace sobre la columna id; el capítulo 6 muestra cómo pedirle que use el slug.

El route model binding ahorra la mitad del código habitual de un controlador. Se usa en todo el resto del tutorial.

Los demás verbos HTTP

Route::get() responde a las peticiones de lectura. Para los formularios y las API, Laravel expone los demás métodos:

php
Route::post('/article', [PostController::class, 'store']);
Route::put('/article/{post}', [PostController::class, 'update']);
Route::delete('/article/{post}', [PostController::class, 'destroy']);

Este tutorial solo usa get: las escrituras pasarán por el panel de administración que se instala en el capítulo 4.

Ver todas las rutas

Este comando lista todo lo que tu aplicación sabe servir:

bash
php artisan route:list --except-vendor

En el proyecto terminado de este tutorial, una vez instalado el panel de administración del capítulo 4, también muestra las rutas del back-office: las declaran clases de su carpeta app/Filament, no el paquete en sí. Para ver solo las páginas del sitio, añada --except-path=admin:

bash
php artisan route:list --except-vendor --except-path=admin
code
  GET|HEAD       / .................................... home › IndexController
  GET|HEAD       article/{post} ................... post › PostController@show
  GET|HEAD       categorie/{category} .......... category › CategoryController
  GET|HEAD       etiquette/{tag} ......................... tag › TagController
  GET|HEAD       recherche .................... search › PostController@search

La opción --except-vendor oculta las rutas añadidas por los paquetes instalados, --except-path=admin descarta las del panel de administración, que sí son suyas. Es el primer comando que hay que lanzar cuando una dirección devuelve un 404 aunque creía haberla declarado.

El capítulo siguiente crea los controladores y las vistas a los que apuntan estas rutas.

Errores frecuentes

Target class [MonController] does not exist La sintaxis 'MonController@methode' ya no está soportada desde Laravel 8: Laravel busca la clase en la raíz del espacio de nombres. Usa la forma [MonController::class, 'methode'] con el use correspondiente.
Una ruta fija capturada por una ruta con parámetro Laravel se detiene en la primera ruta que coincide. Declara /recherche antes que /{slug}, o la segunda interceptará a la primera.
Una ruta declarada devuelve igualmente un 404 Lanza php artisan route:list --except-vendor para ver lo que la aplicación sabe servir realmente.
Newsletter

Las nuevas pruebas, tutoriales y proyectos, por correo.

Pruebas reproducibles, código versionado, resultados fechados. Nunca spam.