Skip to main content

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 en bootstrap/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

Con este único archivo puedes configurar el enrutamiento, los middlewares y el manejo de excepciones. La configuración que en Laravel 10 y anteriores estaba repartida entre app/Http/Kernel.php, app/Console/Kernel.php y app/Exceptions/Handler.php se concentra aquí.

bootstrap/providers.php — lista de service providers

Este archivo es el lugar donde se registran los service providers. En Laravel 10 se declaraban en el array providers de config/app.php; ahora esa lista se ha separado en bootstrap/providers.php. Por defecto en Laravel 11 solo aparece AppServiceProvider.
Cuando instalas un paquete con composer require, el paquete puede actualizar automáticamente bootstrap/providers.php. config/app.php no ha dejado de leerse, pero ahora el lugar recomendado para registrar providers nuevos es bootstrap/providers.php.

Cambios en el directorio routes/

Por defecto no existen api.php ni channels.php. Si los necesitas, los generas con comandos Artisan.
También puedes definir el schedule en routes/console.php.

Archivos eliminados

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.
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.
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.
Este método realiza lo siguiente:
  1. Determina el directorio raíz de la aplicación a partir de basePath.
  2. Crea una instancia de Application.
  3. La envuelve con ApplicationBuilder y aplica la configuración por defecto.
  4. Devuelve la instancia de ApplicationBuilder.
Un detalle importante: dentro de 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

Al llamar a 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

Internamente registra una callback en AppRouteServiceProvider::loadRoutesUsing() y registra el propio AppRouteServiceProvider durante el booting de la aplicación.
Puntos clave:
  • A las rutas api se les aplican automáticamente el grupo de middleware api y el prefijo /api.
  • Si pasas una cadena a health, se registra automáticamente un endpoint de health check (por defecto /up).
  • La ruta de health queda excluida incluso en modo mantenimiento (se configura con PreventRequestsDuringMaintenance::except()).
  • Ten en cuenta que api se registra antes que web. 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

Como 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.
Si pasas withBootstrapProviders: false, dejará de cargarse bootstrap/providers.php. Omite ese parámetro salvo que tengas una razón concreta.

Otros métodos principales

Intención del diseño: por qué es así

Configuración «code first»

El app/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 que api.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:
  1. register() de todos los ServiceProvider.
  2. registered() de Application.
  3. booting() de Application.
  4. boot() de todos los ServiceProvider.
  5. booted() de Application.
Puedes comprobar el orden añadiendo el siguiente código a AppServiceProvider.
Los métodos 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.
Última modificación el 13 de julio de 2026