Common questions and answers when working with the Slim Application Skeleton introduced in Laravel 11. Aimed at developers joining a project mid-way or learning from older books and tutorials.
Use this file to discover all available pages before exploring further.
Laravel 11 introduced the “Slim Application Skeleton,” which significantly changed the application structure. This FAQ covers points that can be confusing when you join a project that has already been upgraded, or when you learned Laravel from books and tutorials written for Laravel 10 or earlier. These are questions frequently asked on Laracasts forums and Stack Overflow around the time Laravel 11 was released.
This FAQ targets new projects (Laravel 11 and later). For upgrading an existing project, see the Migration Guide.
Few config files exist
In the new structure, config files that are rarely changed have been removed from the project. The framework’s own config/ directory is used for those files.The project-side config/ and the framework-side config/ are merged, with the project side taking precedence. You can create a file at any point when customization is needed and it will be picked up.
# Inspect a config file inside the frameworkcat vendor/laravel/framework/config/cors.php# Copy it to the project side to customizephp artisan config:publish cors
$this->validate() / $this->authorize() not available in controllers
In the new structure, App\Http\Controllers\Controller is an empty class — it does not extend Illuminate\Routing\Controller and does not use the ValidatesRequests or AuthorizesRequests traits.
// Use $request->validate() insteadpublic function store(Request $request){ $validated = $request->validate([ 'title' => 'required|string|max:255', ]);}// Use Gate::authorize() insteaduse Illuminate\Support\Facades\Gate;public function update(Request $request, Post $post){ Gate::authorize('update', $post);}
If you use these frequently, you can restore App\Http\Controllers\Controller to the Laravel 10 style:
<?phpnamespace 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;}
app/Http/Middleware and app/Http/Kernel.php missing — middleware configuration
In the new structure, app/Http/Kernel.php has been removed. Middleware configuration is now done via withMiddleware() in bootstrap/app.php.
// bootstrap/app.php->withMiddleware(function (Middleware $middleware) { // Settings previously configured in TrustProxies middleware // are now available as methods on the Middleware class $middleware->trustProxies(at: '*'); // Add a global middleware $middleware->append(\App\Http\Middleware\MyMiddleware::class); // Set a route alias $middleware->alias([ 'my-middleware' => \App\Http\Middleware\MyMiddleware::class, ]); // Customize the web / api middleware group $middleware->web(append: [ \App\Http\Middleware\HandleInertiaRequests::class, ]);})
Custom middleware files themselves are still created in app/Http/Middleware/.
$this->middleware() not available in controllers
$this->middleware() is a feature of Illuminate\Routing\Controller. It is not available in the new structure’s empty base controller.Instead, implement the HasMiddleware interface and define a middleware() method:
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']), ]; }}
In Laravel 13 and later, you can also use the #[Middleware] attribute:
use Illuminate\Routing\Controllers\HasMiddleware;use App\Http\Middleware\EnsureTokenIsValid;#[Middleware(EnsureTokenIsValid::class)]class UserController extends Controller{ // ...}
authorizeResource() depends on the AuthorizesRequests trait, which is not included in the new structure’s empty base controller.There are several ways to address this.1. Restore the base controller to the Laravel 10 style (easiest)
// app/Http/Controllers/Controller.phpuse Illuminate\Foundation\Auth\Access\AuthorizesRequests;use Illuminate\Routing\Controller as BaseController;abstract class Controller extends BaseController{ use AuthorizesRequests;}
This makes $this->authorizeResource() available again.2. Use the #[Authorize] attribute on each method (Laravel 13+)
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) { /* ... */ }}
In the new structure, app/Console/Kernel.php has been removed. The location for defining scheduled tasks has changed.Define schedules in routes/console.php (recommended):
In the new structure, EventServiceProvider has been removed, and manual event and listener registration is no longer required.Auto-discovery: Declare the event class as a type hint on the handle() method of your listener class, and it will be registered automatically.
namespace App\Listeners;use App\Events\OrderShipped;class SendShipmentNotification{ // Type-hint the event class in handle() — registration is automatic public function handle(OrderShipped $event): void { // ... }}
If you need to register manually, do it in AppServiceProvider::boot():
use Illuminate\Support\Facades\Event;public function boot(): void{ Event::listen( OrderShipped::class, SendShipmentNotification::class, );}
How to add service providers (no providers key in config/app.php)
In the new structure, the list of service providers moved from config/app.php to bootstrap/providers.php.
Full control (equivalent to Laravel 10’s RouteServiceProvider):Specifying using disables Laravel’s default route registration entirely, giving you full control.
If the file starts with return Application::configure(..., it uses the new structure. Otherwise, the project was upgraded from the legacy structure. To migrate a legacy project to the new structure, see the Migration Guide.