Comparación con Laravel 10 y anteriores
En Laravel 11 la estructura de la aplicación se ha rediseñado profundamente con el llamado «Slim Application Skeleton». El cambio más importante es la eliminación de la dispersión de configuración: todo se concentra enbootstrap/app.php.
Este cambio es para proyectos nuevos. Si actualizas una aplicación existente de Laravel 10, la estructura antigua seguirá funcionando sin problemas.
Nueva estructura de directorios y archivos
Estructura de directorios del skeleton
bootstrap/app.php — el centro de la configuración de la aplicación
app/Http/Kernel.php, app/Console/Kernel.php y app/Exceptions/Handler.php se concentra aquí.
bootstrap/providers.php — lista de service providers
providers de config/app.php; ahora esa lista se ha separado en bootstrap/providers.php. Por defecto en Laravel 11 solo aparece AppServiceProvider.
Cambios en el directorio routes/
api.php ni channels.php. Si los necesitas, los generas con comandos Artisan.
routes/console.php.
Archivos eliminados
Eliminación de app/Http/Kernel.php
Eliminación de app/Http/Kernel.php
El kernel HTTP se ha integrado en la clase
Illuminate\Foundation\Http\Kernel del framework. La personalización de middlewares se hace con withMiddleware() en bootstrap/app.php.Eliminación de app/Console/Kernel.php
Eliminación de app/Console/Kernel.php
Las dos responsabilidades del kernel de consola se han separado. Los comandos de Artisan se colocan en
app/Console/Commands/ y se autodetectan; el schedule se declara en routes/console.php.Eliminación de app/Exceptions/Handler.php
Eliminación de app/Exceptions/Handler.php
El handler de excepciones se ha integrado en la clase
Illuminate\Foundation\Exceptions\Handler del framework. La personalización se hace con withExceptions() en bootstrap/app.php.Cómo funciona Application::configure()
Implementación interna en el framework
Application::configure() es un método estático de Illuminate\Foundation\Application.
- Determina el directorio raíz de la aplicación a partir de
basePath. - Crea una instancia de
Application. - La envuelve con
ApplicationBuildery aplica la configuración por defecto. - Devuelve la instancia de
ApplicationBuilder.
configure() ya se han llamado withKernels() / withEvents() / withCommands() / withProviders(). No necesitas volver a invocarlas en bootstrap/app.php.
Flujo de configuración con method chaining
create(), se extrae la instancia de Application del ApplicationBuilder, y esa Application es lo que retorna bootstrap/app.php.
Flujo desde la petición hasta el arranque de la aplicación
public/index.php es el punto de entrada; carga bootstrap/app.php para obtener Application. A continuación, el HTTP Kernel pasa la petición por el pipeline de middlewares y el router la envía al controlador correspondiente.
Métodos principales de ApplicationBuilder en profundidad
withRouting() — el proceso interno del registro de rutas
AppRouteServiceProvider::loadRoutesUsing() y registra el propio AppRouteServiceProvider durante el booting de la aplicación.
- A las rutas
apise les aplican automáticamente el grupo de middlewareapiy el prefijo/api. - Si pasas una cadena a
health, se registra automáticamente un endpoint de health check (por defecto/up). - La ruta de
healthqueda excluida incluso en modo mantenimiento (se configura conPreventRequestsDuringMaintenance::except()). - Ten en cuenta que
apise registra antes queweb. Si defines rutas web y de API en la misma ruta, prevalecerá la de API. - Si pasas una cadena a
pages, se habilita el enrutamiento de Laravel Folio.
withMiddleware() — personalización de middlewares
withMiddleware() ejecuta la callback después de que se haya resuelto HttpKernel, gracias al hook afterResolving(). El objeto Middleware que se pasa a la callback ofrece numerosos métodos de personalización.
withExceptions() — configuración del manejo de excepciones
withExceptions() registra la clase Handler del framework como singleton y luego programa la callback con afterResolving(). A la callback se le pasa un wrapper Exceptions.
withProviders() — registro de service providers
Application::configure() llama por defecto a withProviders(), bootstrap/providers.php se carga automáticamente. Si quieres añadir providers adicionales, tienes que llamarlo explícitamente en bootstrap/app.php.
Otros métodos principales
Intención del diseño: por qué es así
Configuración «code first»
Elapp/Http/Kernel.php de Laravel 10 y anteriores utilizaba un estilo en el que los middlewares se enumeraban en arrays. Era un estilo cercano a un archivo de configuración, con la desventaja de que no aprovechaba bien el sistema de tipos de PHP ni el soporte del IDE.
En Laravel 11 se pasa al estilo callback withMiddleware(function (Middleware $middleware) { ... }). Así se dispone de autocompletado por tipos y se pueden escribir configuraciones dinámicas de forma natural, con condicionales, bucles y otras estructuras.
De «convención sobre configuración» a «configuración explícita»
Hacer queapi.php sea opt-in resuelve el hecho de que el grupo de middleware api se cargaba siempre incluso en aplicaciones que no usaban rutas de API. La idea es que las funcionalidades no utilizadas simplemente no existen por defecto.
El uso del hook afterResolving()
En withMiddleware() y withExceptions() se recurre a afterResolving() para evitar problemas de orden en la configuración. Los métodos de ApplicationBuilder se llaman antes de que la aplicación se arranque por completo, pero la aplicación real de la configuración (aplicarla al kernel) queda diferida hasta que el kernel se resuelve por primera vez.
Ejemplos prácticos de personalización
Convivencia de API y Web
Personalización de middlewares
Centralizar el schedule en bootstrap/app.php
El schedule también puede escribirse en routes/console.php, pero con withSchedule() puedes concentrarlo en bootstrap/app.php.
Personalización del manejo de excepciones
Gestionar bindings del contenedor en bootstrap/app.php
En aplicaciones pequeñas puedes escribir bindings sencillos directamente en bootstrap/app.php en lugar de en AppServiceProvider.
Orden del proceso de arranque de Laravel
Al arrancar una aplicación de Laravel, los service providers y los hooks de Application se ejecutan en este orden:register()de todos los ServiceProvider.registered()de Application.booting()de Application.boot()de todos los ServiceProvider.booted()de Application.
AppServiceProvider.
registered(), booting() y booted() de ApplicationBuilder simplemente registran callbacks en Application. Normalmente no necesitas usarlos, pero permiten operaciones especiales como modificar el Kernel en booted() cuando ya está listo.
Próximos pasos
Contenedor de servicios
Entiende cómo funciona el contenedor de servicios que utiliza internamente
ApplicationBuilder.FAQ de la nueva estructura de aplicación
Reúne preguntas frecuentes y respuestas sobre la nueva estructura de aplicación.