> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# FAQ de la nueva estructura de aplicación de Laravel 11 y posteriores

> Recopilación de preguntas frecuentes y respuestas al migrar al Slim Application Skeleton de Laravel 11 y posteriores. Dirigida a quienes se incorporan a proyectos actualizados manteniendo la estructura antigua o a quienes aprendieron con libros o tutoriales anteriores.

En Laravel 11 la estructura de la aplicación cambió notablemente con el llamado «Slim Application Skeleton». Este documento reúne los puntos que suelen resultar confusos cuando te incorporas a un proyecto que se actualizó conservando la estructura antigua o cuando aprendiste con libros y tutoriales de Laravel 10 o anteriores. Son preguntas frecuentes que aparecían en los foros de Laracasts y en Stack Overflow cuando se lanzó Laravel 11.

<Info>
  Este FAQ se centra en **proyectos nuevos** (Laravel 11 o posterior). Si necesitas actualizar un proyecto existente, consulta la [guía de migración](/es/advanced/app-structure-migration).
</Info>

<AccordionGroup>
  <Accordion title="Hay pocos archivos en config">
    En la nueva estructura, se han eliminado del proyecto los archivos de `config` que rara vez se modifican. Para esos archivos se usa el `config/` incluido en el framework.

    Los `config/` del proyecto y del framework se fusionan, y **el del proyecto tiene prioridad**. Cuando necesites personalizar algo, crea el archivo y los cambios se aplicarán.

    ```bash theme={null}
    # Consulta el config del framework
    cat vendor/laravel/framework/config/cors.php

    # Cópialo al proyecto y personalízalo
    php artisan config:publish cors
    ```
  </Accordion>

  <Accordion title="No puedo usar $this->validate() ni $this->authorize() en un controlador">
    En la nueva estructura de Laravel 11, `App\Http\Controllers\Controller` es una clase vacía, no extiende `Illuminate\Routing\Controller` y no usa los traits `ValidatesRequests` ni `AuthorizesRequests`.

    | Laravel 10                               | Laravel 11  |
    | ---------------------------------------- | ----------- |
    | Extiende `Illuminate\Routing\Controller` | Clase vacía |
    | Usa el trait `ValidatesRequests`         | No          |
    | Usa el trait `AuthorizesRequests`        | No          |

    Referencia: [Controller de Laravel 10](https://github.com/laravel/laravel/blob/10.x/app/Http/Controllers/Controller.php) vs [Controller de Laravel 11](https://github.com/laravel/laravel/blob/11.x/app/Http/Controllers/Controller.php)

    **Alternativas:**

    ```php theme={null}
    // Usa $request->validate()
    public function store(Request $request)
    {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
        ]);
    }

    // Usa Gate::authorize()
    use Illuminate\Support\Facades\Gate;

    public function update(Request $request, Post $post)
    {
        Gate::authorize('update', $post);
    }
    ```

    Si los usas con frecuencia, también puedes restaurar `App\Http\Controllers\Controller` como en Laravel 10.

    ```php theme={null}
    <?php

    namespace App\Http\Controllers;

    use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
    use Illuminate\Foundation\Validation\ValidatesRequests;
    use Illuminate\Routing\Controller as BaseController;

    abstract class Controller extends BaseController
    {
        use AuthorizesRequests, ValidatesRequests;
    }
    ```
  </Accordion>

  <Accordion title="No existe app/Http/Middleware y no puedo cambiar la configuración de middleware / no hay app/Http/Kernel.php">
    En la nueva estructura, `app/Http/Kernel.php` ha desaparecido. La configuración del middleware se hace mediante `withMiddleware()` en `bootstrap/app.php`.

    ```php theme={null}
    // bootstrap/app.php
    ->withMiddleware(function (Middleware $middleware) {
        // Todo lo que antes se configuraba en middlewares como TrustProxies ahora se hace con métodos de la clase Middleware
        $middleware->trustProxies(at: '*');

        // Añadir middleware global
        $middleware->append(\App\Http\Middleware\MyMiddleware::class);

        // Configurar alias para grupos de rutas
        $middleware->alias([
            'my-middleware' => \App\Http\Middleware\MyMiddleware::class,
        ]);

        // Personalizar los grupos de middleware Web / API
        $middleware->web(append: [
            \App\Http\Middleware\HandleInertiaRequests::class,
        ]);
    })
    ```

    Los archivos de los middlewares personalizados siguen creándose en `app/Http/Middleware/`.
  </Accordion>

  <Accordion title="No puedo usar $this->middleware() dentro de un controlador">
    `$this->middleware()` era una funcionalidad de `Illuminate\Routing\Controller` y no está disponible en la nueva clase base vacía.

    En su lugar, implementa la interfaz `HasMiddleware` y define el método `middleware()`.

    ```php theme={null}
    use Illuminate\Routing\Controllers\HasMiddleware;
    use Illuminate\Routing\Controllers\Middleware;

    class UserController extends Controller implements HasMiddleware
    {
        public static function middleware(): array
        {
            return [
                'auth',
                new Middleware('log', only: ['index']),
                new Middleware('subscribed', except: ['index']),
            ];
        }
    }
    ```

    Desde Laravel 13, también puedes utilizar el atributo `#[Middleware]`.

    ```php theme={null}
    use Illuminate\Routing\Controllers\HasMiddleware;
    use App\Http\Middleware\EnsureTokenIsValid;

    #[Middleware(EnsureTokenIsValid::class)]
    class UserController extends Controller
    {
        // ...
    }
    ```

    Referencia: [Middleware de controlador](https://laravel.com/docs/13.x/controllers#controller-middleware)
  </Accordion>

  <Accordion title="No existe $this->authorizeResource()">
    `authorizeResource()` depende del trait `AuthorizesRequests`, por lo que no está disponible en la clase base vacía de la nueva estructura.

    **Hay varias formas de resolverlo.**

    **1. Devolver la clase base al estilo Laravel 10 (la opción más sencilla)**

    ```php theme={null}
    // app/Http/Controllers/Controller.php
    use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
    use Illuminate\Routing\Controller as BaseController;

    abstract class Controller extends BaseController
    {
        use AuthorizesRequests;
    }
    ```

    Así podrás volver a usar `$this->authorizeResource()`.

    **2. Aplicar el atributo `#[Authorize]` de Laravel 13 a cada método**

    ```php theme={null}
    use Illuminate\Routing\Attributes\Controllers\Authorize;
    use App\Models\Post;

    class PostController extends Controller
    {
        #[Authorize('view', 'post')]
        public function show(Post $post) { /* ... */ }

        #[Authorize('update', 'post')]
        public function update(Request $request, Post $post) { /* ... */ }
    }
    ```
  </Accordion>

  <Accordion title="No existe app/Console/Kernel.php y no puedo configurar el Schedule">
    En la nueva estructura, `app/Console/Kernel.php` ha desaparecido y el sitio para configurar el schedule ha cambiado.

    **Definirlo en `routes/console.php` (recomendado):**

    ```php theme={null}
    // routes/console.php
    use Illuminate\Support\Facades\Schedule;

    Schedule::command('emails:send')->daily();
    Schedule::job(new SendEmails)->everyFiveMinutes();
    ```

    **Definirlo en `bootstrap/app.php`:**

    ```php theme={null}
    ->withSchedule(function (Schedule $schedule) {
        $schedule->command('emails:send')->daily();
    })
    ```
  </Accordion>

  <Accordion title="No sé cómo registrar eventos y listeners">
    En la nueva estructura, `EventServiceProvider` ha desaparecido y ya no es necesario registrar manualmente los eventos y sus listeners.

    **Cómo funciona el registro automático:** basta con declarar el tipo del evento en el argumento del método `handle()` del listener para que se registre automáticamente.

    ```php theme={null}
    namespace App\Listeners;

    use App\Events\OrderShipped;

    class SendShipmentNotification
    {
        // Con solo declarar la clase del evento como argumento de handle() se registra automáticamente
        public function handle(OrderShipped $event): void
        {
            // ...
        }
    }
    ```

    Si necesitas registrarlo manualmente, hazlo en `AppServiceProvider::boot()`.

    ```php theme={null}
    use Illuminate\Support\Facades\Event;

    public function boot(): void
    {
        Event::listen(
            OrderShipped::class,
            SendShipmentNotification::class,
        );
    }
    ```
  </Accordion>

  <Accordion title="No sé cómo añadir un service provider a config/app.php">
    En la nueva estructura, la lista de service providers se gestiona desde `bootstrap/providers.php` en lugar de `config/app.php`.

    ```php theme={null}
    // bootstrap/providers.php
    return [
        App\Providers\AppServiceProvider::class,
        App\Providers\MyCustomServiceProvider::class, // ← añádelo aquí
    ];
    ```

    Los providers creados con `artisan make:provider` se añaden aquí automáticamente.
  </Accordion>

  <Accordion title="No existe app/Exceptions/Handler.php">
    En la nueva estructura, `app/Exceptions/Handler.php` ha desaparecido y el manejo de excepciones se configura con `withExceptions()` en `bootstrap/app.php`.

    ```php theme={null}
    // bootstrap/app.php
    ->withExceptions(function (Exceptions $exceptions) {
        // No reportar una excepción concreta
        $exceptions->dontReport(InvalidOrderException::class);

        // Renderizado personalizado
        $exceptions->render(function (InvalidOrderException $e, Request $request) {
            return response()->view('errors.invalid-order', status: 500);
        });

        // Cambiar el destino de la redirección cuando no está autenticado
        $exceptions->shouldRenderJsonWhen(function (Request $request, Throwable $e) {
            return $request->is('api/*');
        });
    })
    ```
  </Accordion>

  <Accordion title="Quiero personalizar el enrutamiento">
    La personalización de las rutas se hace con `withRouting()` en `bootstrap/app.php`.

    **Añadir archivos de rutas:**

    ```php theme={null}
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        then: function () {
            Route::middleware('web')
                ->prefix('admin')
                ->group(base_path('routes/admin.php'));
        },
    )
    ```

    **Control completo (equivalente al `RouteServiceProvider` de Laravel 10):**

    Si especificas `using`, el registro de rutas por defecto de Laravel queda completamente desactivado y podrás controlar todo por tu cuenta.

    ```php theme={null}
    ->withRouting(
        using: function () {
            Route::middleware('web')
                ->group(base_path('routes/web.php'));

            Route::middleware('api')
                ->prefix('api')
                ->group(base_path('routes/api.php'));
        },
    )
    ```
  </Accordion>

  <Accordion title="Quiero sustituir uno de los ServiceProvider por defecto de Laravel">
    Si añades una clave `providers` en `config/app.php`, se fusionará con el `config/app.php` interno del framework y surtirá efecto.

    ```php theme={null}
    // config/app.php
    use Illuminate\Support\ServiceProvider;

    return [
        // ...
        'providers' => ServiceProvider::defaultProviders()->replace([
            Illuminate\Foo\FooServiceProvider::class => Bar\BarServiceProvider::class,
        ])->toArray(),
    ];
    ```

    Con el método `replace()` puedes sustituir un provider por defecto por tu propia implementación.
  </Accordion>

  <Accordion title="No existe routes/api.php">
    Desde Laravel 11, las funciones de API no están incluidas por defecto; se instalan de forma individual cuando se necesitan.

    ```bash theme={null}
    php artisan install:api
    ```

    Este comando crea y configura lo siguiente:

    * `routes/api.php`
    * Configuración de [Laravel Sanctum](https://laravel.com/docs/sanctum) para la autenticación de la API.
    * Registro de las rutas de API en `bootstrap/app.php`.
  </Accordion>

  <Accordion title="No existe routes/channels.php">
    Desde Laravel 11, la funcionalidad de broadcasting tampoco viene incluida por defecto; se instala aparte cuando se necesita.

    ```bash theme={null}
    php artisan install:broadcasting
    ```

    Este comando crea y configura lo siguiente:

    * `routes/channels.php`
    * Configuración de instalación de [Laravel Reverb](https://laravel.com/docs/reverb).
    * Archivo de configuración de broadcasting.
  </Accordion>

  <Accordion title="Quiero saber si un proyecto al que me incorporo usa la nueva o la vieja estructura">
    Revisa el contenido de `bootstrap/app.php`.

    **Nueva estructura de Laravel 11 (o ya migrada):**

    ```php theme={null}
    // bootstrap/app.php
    return Application::configure(basePath: dirname(__DIR__))
        ->withRouting(...)
        ->withMiddleware(...)
        ->withExceptions(...)
        ->create();
    ```

    **Proyecto de Laravel 10 o anterior actualizado sin migrar la estructura:**

    ```php theme={null}
    // bootstrap/app.php
    $app = new Illuminate\Foundation\Application(
        $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
    );

    $app->singleton(
        Illuminate\Contracts\Http\Kernel::class,
        App\Http\Kernel::class
    );
    // ...
    ```

    Si tiene el formato `return Application::configure(...`, es la nueva estructura; en caso contrario, es un proyecto actualizado manteniendo la estructura antigua. Para migrar un proyecto de la estructura antigua a la nueva, consulta la [guía de migración](/es/advanced/app-structure-migration).
  </Accordion>
</AccordionGroup>

## Páginas relacionadas

<Card title="Estructura de aplicación en Laravel 11 y posteriores" icon="sitemap" href="/es/advanced/app-structure">
  Explica en detalle la nueva estructura de la aplicación y la implementación interna de `ApplicationBuilder`.
</Card>

<Card title="Guía de migración de la estructura antigua a la nueva" icon="arrow-right" href="/es/advanced/app-structure-migration">
  Cubre los pasos para migrar un proyecto desde la estructura antigua de Laravel 10 a la nueva estructura de Laravel 11 y posteriores.
</Card>


## Related topics

- [Estructura de aplicación en Laravel 11 y posteriores](/es/advanced/app-structure.md)
- [Guía de migración de la estructura antigua a la nueva](/es/advanced/app-structure-migration.md)
- [Actualización de Laravel 10 a 11](/es/blog/upgrade-10-to-11.md)
- [Instalación](/es/installation.md)
- [Estructura de directorios](/es/directory-structure.md)
