Laravel y el ciclo de vida de las solicitudes
Lección 8 / 8
Laravel Guía Laravel
El routing es uno de los aspectos esenciales de una aplicación web y es, obviamente, la base de un proyecto Laravel. Routing significa el mecanismo mediante el cual las solicitudes HTTP se enrutan (route) a la parte del código que las administrará y es la base del ciclo de vida de una solicitud HTTP administrada por una aplicación Laravel.
En Laravel, el routing se configura y gestiona mediante el registro de rutas en los archivos route/web.php y route/api.php, que gestionan respectivamente las solicitudes relacionadas con la interfaz web de la aplicación y las solicitudes de tipo API RESTful.
Conocer los mecanismos de trabajo del routing en Laravel es importante para comprender mejor el propósito, el comportamiento esperado y las interacciones entre los diversos componentes que componen una aplicación web Laravel, logrando así superar la sensación inicial de "sucede como por arte de magia".
Veamos entonces, en detalle, el ciclo de vida de solicitud HTTP en una aplicación Laravel. Es decir, que sucede "en el server" cuando llega una solicitud HTTP de un client.
Server web y aplicación web Laravel
En el mundo del web es importante distinguir entre server web y aplicación web.
El servidor web es una aplicación por derecho propio que básicamente se encarga de recibir solicitudes HTTP de los clientes y decidir qué archivo está asociado con el recurso solicitado.
Hagamos un pequeño ejemplo: tenemos una directory de nombre /opt/website/ que tiene dentro los archivos index.html y style.css. Si iniciamos el server web configurado de la siguiente manera:
root: /opt/website/
req: / -> index.html
req: /* -> *
Estamos diciendo que:
- si el client manda una solicitud HTTP para el recurso /, entonces el server sustituye el archivo /opt/website/index.html
- para cualquier otra solicitud el server devuelve el archivo solicitado si está presente en /opt/website/website/
Si el archivo solicitado no existe, el web server ofrecerá una respuesta HTTP con status code 404 Not Found.
Un server web opera a nivel de solicitud y respuesta HTTP, limitándose a clasificar las solicitudes hacia los archivos incluidos en un directory determinado.
Un sitio web estático, es decir, compuesto solo de páginas HTML que no cambian en función de la solicitud realizada o que no requieren la presencia de formularios para enviar datos, puede estar disponible en la web cargando los archivos en una máquina que ejecuta solo un servidor web, gestionando adecuadamente los enlaces y directorios en disco.
Una aplicación Laravel necesita un servidor web para recibir solicitudes HTTP y devolver respuestas, pero el servidor web básicamente está configurado de la siguiente manera:
root: /opt/app-laravel/public/
req: /* -> run(php index.php)
Es decir: por cada solicitud HTTP recibida ejecuta el script public/index.php del proyecto Laravel.
El archivo index.php en Laravel
El archivo public/index.php de un proyecto Laravel es, por lo tanto, el script PHP que se invoca cada vez que llega una solicitud a nuestro servidor.
No hay mucho código en este archivo, solo lo que se necesita para cargar el resto del framework de Laravel. De hecho, aparte del necesario requerimiento del autoload, encontramos solo
$app = require_once __DIR__.'/../bootstrap/app.php';
$kernel = $app->make(Kernel::class);
$response = $kernel->handle(
$request = Request::capture()
)->send();
$kernel->terminate($request, $response);
Que podemos interpretar de la siguiente manera:
- recupera una instancia de la aplicación Laravel $app
- carga el $kernel oportuno (en base al tipo de solicitud que llega será un kernel de tipo HTTP o consol)
- gestiona la $request que llega al kernel y envía una $response
Este mini ciclo se repite con cada solicitud que llega al servidor, pasando la solicitud de una capa a otra hasta llegar al código real que manejará y devolverá el contenido de la respuesta.
La selección del middleware
Las solicitudes de tipo HTTP continúan su viaje siguiendo un camino aparentemente tortuoso, nuevamente ligado al tipo de solicitud recibida.
Las versiones más recientes de Laravel (en esta guía estamos usando la versión 9.x actualmente disponible) ofrecen, de hecho, la posibilidad de distinguir dos "grupos" diferentes de rutas, definidas como middleware.
Cuando se inicializa la aplicación Laravel, se carga un servicio interno para el manejo de rutas. Este servicio corresponde al contenido del archivo app/Providers/RouteServiceProvider.php, es decir, la clase App\Providers\RouteServiceProvider. La versión predeterminada de este servicio incluye lo siguiente:
$this->routes(function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'))
Route::middleware('web')
->group(base_path('routes/web.php'));
});
es decir, todas las solicitudes de recursos cuya ruta comienza con api pertenecen al middleware api y se clasificarán en el archivo route/api.php para su clasificación posterior. Cualquier otra solicitud se reenvía al middleware web y se reenviará mediante el archivo route/web.php.
Solicitud |
Middleware |
---|---|
GET /api/orders/ |
api |
POST /page/form |
web |
GET /docs/api/ |
web |
GET /blog/2022/12/23/post.html |
web |
DELETE /api/orders/23455 |
api |
DELETE /order/23455 |
web |
NOTA: lo que se ha descrito hasta ahora es la configuración presente en una aplicación Laravel recién creada a partir del template de default. Puedes cambiar estas configuraciones según tus necesidades, por ejemplo, eliminar completamente el middleware API en caso de que no necesitse las API RESTful, pero quieras usar Laravel para compilar solo en el sitio web.
La selección de las rutas registradas
Una vez que se ha identificado el middleware, nuestra solicitud HTTP continúa su viaje hasta su destino final.
La responsabilidad ahora recae en los archivos route/web.php y route/api.php que, aunque de forma ligeramente diferente dada la diferente naturaleza del tipo de solicitud que manejan, contienen las rutas reales registradas.
// routes/web.php
Route::get('/', function () {
return view('welcome');
});
Route::get('/hello', function () {
return "Hello Laravel";
});
// routes/api.php
Route::middleware('auth:sanctum')->get('/orders', function (Request $request) {
return $request->orders();
});
Por lo tanto, si hay una ruta registrada para la ruta de la solicitud que se está manejando, entonces se ejecutará la función correspondiente y se devolverá el retorno de la función misma.
Por ejemplo, limitándonos solo a solicitudes en el middleware web:
- en caso de que llegase una solicitud GET /hello, entonces será devuelto el texto “Hello Laravel” que se convertirá en el body de la respuesta HTTP con status 200 OK
- para la solicitud GET / se invocará una función dedicada que hace el rendering de una view, es decir busca el archivo template asociato, lo elabora y devuelve el resultado como texto (muy probablemente HTML) que, también aquí, se convertirá en el body de una respuesta HTTP con status 200 OK
- cualquier otra solicitud, tanto por método como por recurso solicitado, al no tener registrada una ruta correspondiente, no se puede satisfacer y Laravel se encargará de preparar y devolver la respuesta con status 404 Not Found
El archivo routes/web.php es, por tanto, el archivo a consultar para saber qué rutas están actualmente registradas y el punto de partida a la hora de definir una nueva ruta.
NOTA: Además de lo descrito hasta ahora, Laravel también permite otra forma de definir una ruta, a través de un controller. Por ahora, considéralo como una forma de agrupar rutas que forman parte del mismo agregado en una sola clase.
Artisan y las rutas en Laravel
Para obtener una lista completa de las rutas registradas de la aplicación Laravel, también es posible usar el oportuno comando Artisan:
php artisan route:list
La opción -v muestra también los middleware asociados, mientras la opción --path permite mostrar solo las rutas que contienen una determinada cadena en el URI:
$ php artisan route:list --path=user -v
GET|HEAD api/user
⇂ api
⇂ App\Http\Middleware\Authenticate:sanctum
GET|HEAD user
⇂ web
Si habéis agregado una ruta y no aparece cuando se ejecuta este comando, probablemente no se agregó correctamente. Laravel, por lo tanto, no podrá manejar solicitudes para esa ruta.
Conclusiones
- el routing es la manera con la que una solicitud HTTP de una determinada URI se envía a un archivo o a una porción de código que se encarga de crear el contenido de la respuesta
- en Laravel es suficiente con registrar una ruta para gestionar las solicitudes
- una ruta registrada se identifica por el método HTTP y por el path del recurso
- una ruta registrada indica también que hacer para construir la respuesta para mandar al cliente
- todas las rutas registradas están presentes en el archivo routes/web.php
- Laravel esconde al desarrollador web gran parte de la gestión de bajo nivel de los mecanismos de routing, pero se puede siempre personalizar la propia app yendo a modificar el contenido de archivos específicos y clases
Anterior
7 Estructura de un pro..Siguiente
9