Skip to content

Laravel

Rapira ejecuta Laravel en modo clásico: el front controller public/index.php de siempre, ejecutado desde cero en cada petición, tal y como lo ejecuta php-fpm. La aplicación no necesita ningún cambio. El modo worker para Laravel está en desarrollo; su estado actual está más abajo, en Modo worker.

Verificado con

  • PHP 8.5.8 — NTS, SAPI embed
  • Rapira 0.6.0
  • Esqueleto de laravel/laravel con laravel/framework v13.23.0

Todo lo que cuenta esta página se ejecutó sobre un esqueleto laravel/laravel con unas cuantas rutas de prueba añadidas, en modo clásico y con un solo proceso worker: enrutado, sesiones, subidas de archivos, cuerpos JSON y de formulario, configuración y rutas cacheadas, respuestas de error y 50 peticiones seguidas.

Requisitos previos

Necesitas Rapira instalado —lo tienes en Instalación— y una aplicación de Laravel que ya te funcione. También necesitas un PHP CLI normal en la máquina para Composer y artisan: Rapira trae PHP como biblioteca (libphp), no como comando php, así que esos pasos se ejecutan con el PHP de tu sistema, que Rapira ni usa ni toca.

Comprueba las extensiones de base de datos antes del primer arranque: un esqueleto recién creado de laravel/laravel viene con una base de datos SQLite y con los drivers de sesión, caché y colas apoyados en base de datos, lo que significa que necesita pdo_sqlite. El PHP que acompaña a las releases de Rapira lo trae: PDO, pdo_sqlite y sqlite3 están en el conjunto de extensiones de la compilación de release, tal y como lista la página de Instalación. Si ejecutas Rapira contra un PHP compilado por ti, asegúrate de que esas extensiones aparecen en tu línea de configure (Compilar desde el código lo cuenta), o apunta Laravel a los drivers de archivo y sync: SESSION_DRIVER=file, CACHE_STORE=file, QUEUE_CONNECTION=sync. Esa es la combinación con la que se verificó esta página.

Ponerlo en marcha

El modo clásico se activa expresamente, así que el comando lo nombra:

bash
rapira serve --classic public/index.php
toml
[pool]
entrypoint = "public/index.php"
classic = true
processes = 4

[http]
listen = "127.0.0.1:8000"

Con un archivo de configuración el comando es rapira serve --config rapira.toml, y un entrypoint relativo se resuelve respecto al directorio del propio archivo. Todas las claves y sus valores por defecto están en la página de Configuración.

Rapira ejecuta el front controller desde cero en cada petición, así que el ciclo de vida del framework es exactamente el que tiene bajo php-fpm: no hay estado residente ni nada que reiniciar entre peticiones. Lo que sí se queda caliente es OPcache: PHP arranca una sola vez en el maestro, antes de hacer fork de ningún worker, así que todos los workers comparten la misma caché de scripts compilados para tu código y para tu árbol vendor/. En Modo clásico tienes cómo funciona.

Para producción, genera antes las cachés del framework; las dos se verificaron en modo clásico, y las mismas comprobaciones pasaron sin cachear y cacheadas:

bash
php artisan config:cache
php artisan route:cache

Rutas y URLs

Rapira no mapea las URL sobre archivos: cada petición ejecuta el front controller y la ruta que Laravel enruta llega en $_SERVER['REQUEST_URI']. El enrutado, la página 404 del propio Laravel para las rutas que no encajan y la generación con url() se verificaron todos: las URL que salen son absolutas y limpias, sin index.php por ninguna parte, y sin sobrescribir nada de $_SERVER ni tocar la configuración de rutas o de URLs.

La ruta de salud /up que trae el esqueleto responde 200, así que sirve como destino del health check de un balanceador de carga o de un contenedor. Los archivos estáticos necesitan algo delante de Rapira: una CDN o el proxy inverso que monta la página En producción. El listener de Rapira habla HTTP en claro y deja $_SERVER['HTTPS'] vacío sea cual sea el valor de X-Forwarded-Proto, así que, cuando ese proxy termina el TLS, configura los proxies de confianza de Laravel; si no, url() generará enlaces http://.

Sesiones, CSRF y formularios

Las sesiones se verificaron con el driver de archivos: la cookie de sesión sale, vuelve en la petición siguiente y cada cliente tiene la suya. CSRF no necesita configuración: el token vive en la sesión y cada petición tiene la misma semántica de proceso nuevo que le da php-fpm. Los envíos de formularios, los cuerpos de petición en JSON y las subidas de archivos se verificaron todos con el mismo montaje. Cuando una ruta lanza una excepción, el manejador de excepciones de Laravel pinta su 500 de siempre y la petición siguiente no se ve afectada.

Modo worker

El modo worker para Laravel está en desarrollo y todavía no se admite: ejecuta Laravel en modo clásico. Aún no hay fecha para la compatibilidad con el modo worker.

El motivo es el ciclo de vida del framework. El contenedor de Laravel no está pensado para sobrevivir a una segunda petición sin ayuda: los bindings se resuelven, los singletons se quedan con la petición actual y las estáticas del framework se van llenando mientras la petición avanza, así que todo eso hay que deshacerlo antes de que llegue la siguiente. Ese desmontaje es justo lo que implementa Octane (laravel/octane), el paquete del propio Laravel para servidores de larga vida. Octane solo funciona en los servidores para los que tiene driver, y Rapira todavía no tiene driver de Octane.

El modo en sí no es el impedimento: Symfony y Yii3 mantienen sus aplicaciones residentes en ese mismo modo SAPI Worker. Lo que falta es el manejo del estado entre peticiones específico de Laravel.

Puedes escribir tu propio script de worker para Laravel, pero mantener la aplicación residente significa rehacer a mano el manejo de estado de Octane: el estado que hay que deshacer está repartido entre el contenedor, los singletons ya resueltos, la pila de petición/sesión/autenticación y las estáticas del propio framework, y uno que se te escape aparece como un objeto de petición caducado o como la sesión de un usuario visible para el siguiente.