Link Search Menu Expand Document

5.7. Enrutamiento

Llegados a este punto, ya debes haber creado tu primera aplicación Laravel (“Hola, mundo”) y habrás aprendido algo fundamental sobre el enrutador: cómo hacer que la solicitud de una URL termine ejecutando un método de un controlador.

En esta sección, profundizaremos en el enrutador, un componente fundamental de cualquier aplicación web.

5.7.1. ¿Qué es el enrutador?

El enrutador de Laravel es el componente que captura las URL solicitadas al servidor y las traduce a invocaciones a métodos de los controladores.

El enrutador es capaz, además, de mapear fragmentos de la URL a variables PHP que serán inyectadas como parámetros a los métodos del controlador.

Esto significa que, si le pides al servidor una ruta como esta:

https://mi-servidor/user/delete/12

…el enrutador puede “trocear” esa URL para extraer los segmentos (“user”, “delete” y “12”). Y tú puedes decidir qué hacer con cada uno de esos segmentos. Lo normal en este ejemplo sería que invocaras el método delete() del controlador UserController, y que ese método recibiera como parámetro el dato 12, que será el id del usuario que se pretende borrar.

Y hay una última cosa que el enrutador puede hacer: distinguir el verbo http empleado para solicitar una página al servidor.

Es decir, para el enrutador no es lo mismo una solicitud enviada por GET que otra enviada por POST. Incluso admite verbos que aún no están soportados por HTML, como DELETE o PUT, y que teóricamente van a formar parte de futuras implementaciones del lenguaje. Un poco más abajo explicaremos qué narices significa todo esto.

5.7.2. Enrutamiento básico

Como vimos en el ejemplo del “Hola, mundo”, hay varias formas de generar una salida HTML desde el enrutador (/routes/web.php). En este código de ejemplo vemos las cuatro formas básicas:

// Forma 1: generar la salida directamente en el enrutador, con un closure (función sin nombre)
Route::get('/hola', function() {
    return "Hola, mundo";
});

// Forma 2: llamar a una función de un controlador sin pasarle parámetros
Route::get('/hola', 'HolaController@show');

// Forma 3: llamar a una función de un controlador pasándole parámetros
Route::get('/hola/{nombre}', 'HolaController@show');

// Forma 4: llamar a una función de un controlador con un parámetro optativo
Route::get('/hola/{nombre?}', 'HolaController@show');

La diferencia esntre la forma 3 y la 4 es que, en la forma 3, la ruta debe llevar forzosamente un dato a continuación de “/hola” (algo como: https://mi-servidor/hola/juan). Si no lo lleva, el enrutador considerará que no se trata de esa ruta y seguirá buscando alguna ruta coincidente en el resto del archivo.

En cambio, en la forma 4, el dato final es optativo, así que el enrutador invocará el método show() del controlador tanto si ese dato aparece en la URL como si no lo hace.

5.7.3. Rutas con nombre

Es MUY recomendable asignar un nombre a las rutas en el enrutador. Esto hace que, más adelante, podamos cambiar la URL de los enlaces sin tener que modificar el código fuente de nuestras vistas.

El nombre se le asigna a una ruta añadiendo ->name('nombre') al final:

Route::get('/contactame', 'Controlador@contacto')->name('contact');

En tu código fuente, debes referirte a esta ruta siempre con la expresión route('contact') (ya veremos exactamente cómo se hace esto), pero el usuario verá la dirección https://servidor/contactame.

En el futuro se puede cambiar la forma en la que lo ve el usuario. Por ejemplo, puedes cambiar Route::get('/contactame'...) por Route::get('/acerca-de'...), pero no tendrás que modificar ni una línea de código más en tu aplicación, porque internamente esa ruta seguirá llamándose route('contact').

5.7.4. Verbos http: GET, POST, PUT, PATCH y DELETE

Además de GET, en el enrutador se pueden enrutar otras acciones:

Route::get();    // Solicitudes habituales
Route::post();   // Recepción de datos de formulario (para insert)
Route::put();    // Recepción de datos para update (también puede escribirse Route::patch(), que no es lo mismo, pero casi)
Route::delete(); // Recepción de datos para delete
Route::match(array('GET','POST'), 'ruta', acción)
                 // Responderá tanto a GET como a POST

Los verbos PUT, PATCH y DELETE no están soportados aún por HTML. Las razones por las que esto ocurre son tan confusas que, sinceramente, creo que ni siquiera en el W3C lo entienden. La cuestión es que aún no existen, y punto.

Es decir, no puedes crear un formulario así: <form method='PUT'>, porque tu navegador no lo entenderá. Solo puedes poner <form method='GET'> o <form method='POST'>.

Cuando trabajes con Laravel, puedes emular PUT, PATCH o DELETE en los formularios así:

<form action="/foo/bar" method="POST">
    @method('DELETE')

Tal vez, llegado a este punto, te estés preguntando qué diferencia hay entre PUT y PATCH. O tal vez no. Salta a la siguiente sección si no te interesan estas sutilezas, y continúa leyendo en caso contrario.

En teoría, una petición enviada por PUT debería culminar con la ejecución de un UPDATE en el servidor que modifique un recurso entero. Es decir, un registro completo de una tabla de la base de datos.

En cambio, PATCH debería emplearse cuando el UPDATE vaya a modificar solo una parte de los campos de un registro, y no todos.

¿Que te parece una chorrada hacer esa distinción? Bueno, lo que tú o yo opinemos no importa demasiado. Todo esto es un estándar y, por lo tanto, hay que comérselo con patatas.

5.7.5. Orden de las rutas

El orden en el que se escriben las rutas en el enrutador es importante.

Por ejemplo, si pedimos la dirección http://mi-servidor/usuario/crear, escribir estas dos rutas en este orden es un error:

Route::get('usuario/{nombre}', 'UsuarioController@show');
Route::get('usuario/crear', 'UsuarioController@create');

El enrutador tratará de mostrar un usuario cuyo nombre sea “crear” (que seguramente no existirá) porque la petición encaja con las dos rutas y el enrutador elegirá la primera ruta que encuentre.

La solución pasa por alterar el orden de las líneas en el enrutador:

Route::get('usuario/crear', 'UsuarioController@create');
Route::get('usuario/{nombre}', 'UsuarioController@show');

De este modo, la petición http://mi-servidor/usuario/crear seguirá encajando en las dos rutas, pero el enrutador elegirá la primera. En cambio, una petición parecida pero con cualquier otro nombre (por ejemplo, http://mi-servidor/usuario/luis), solo encajará con la segunda ruta.

5.7.6. Servidor RESTful

Un servidor RESTful es aquel que responde a la arquitectura REST.

La arquitectura REST no es más que una forma estandarizada de construir un servidor para que realice las tareas típicas de mantenimiento de recursos. Y los recursos pueden ser cualquier cosa que se almacene en el servidor: usuarios, clientes, productos, películas, facturas…

Es decir: el 99% de las veces, los recursos son registros en una tabla de la base de datos.

El enrutador de un servidor RESTful contendrá las 7 operaciones definidas en la arquitectura REST para cada recurso accesible desde la red, y que permiten manipular el recurso: mostrarlo, buscarlo, insertarlo, modificarlo o borrarlo.

Por ejemplo, para un recurso llamado “user”, esas 7 operaciones son:

Route::get('user', 'UserController@index')->name('user.index');                // Recupera todos los usuarios
Route::get('user/{user}', 'UserController@show')->name('user.show');           // Recupera un usuario concreto con id = user
Route::get('user/crear', 'UserController@create')->name('user.create');        // Lanza el formulario de creación de usuarios
Route::post('user/{user}', 'UserController@store')->name('user.store');        // Recoge los datos del formulario y los inserta en la base de datos
Route::get('user/{user}/edit', 'UserController@edit')->name('user.edit');      // Lanza el formulario de modificación de usuarios
Route::patch('user/{user}', 'UserController@update')->name('user.update');     // Recoge los datos del formulario y modifica el usuario de la base de datos
Route::delete('user/{user}', 'UserController@destroy')->name('user.destroy');  // Elimina al usuario de la base de datos

Ten encuenta que, si estás construyendo un servidor RESTful, debes respetar escrupulosamente los nombres y URLs de las rutas. Así, cualquier otro usuario o aplicación que use tu servidor sabrá cómo manipular los recursos sin necesidad de consultar la documentación técnica.

Laravel te permite resumir esas entradas del enrutador en una sola línea que engloba a las siete rutas REST:

Route::resource('user');