跳转到主要内容
Laravel 11 以「Slim Application Skeleton」为名,大幅调整了应用结构。当你中途加入一个仍以旧结构升级的项目,或以 Laravel 10 及更早的书籍、教程学习时,容易感到困惑。本文汇总的正是 Laravel 11 发布时在 Laracasts 论坛和 Stack Overflow 上最常被问到的问题。
本 FAQ 面向新项目(Laravel 11 及以上)。既有项目的升级步骤请参考迁移指南
新结构从项目中删除了变更频率较低的 config 文件,这些文件转而使用框架内的 config/项目侧的 config/ 与框架侧的 config/ 会进行合并,以项目侧为优先。只有在需要自定义时才创建对应文件,即可生效。
# 查看框架内的 config
cat vendor/laravel/framework/config/cors.php

# 复制到项目侧进行自定义
php artisan config:publish cors
在 Laravel 11 的新结构中,App\Http\Controllers\Controller 是一个空类,不再继承 Illuminate\Routing\Controller,也不再使用 ValidatesRequests / AuthorizesRequests trait。
Laravel 10Laravel 11
继承 Illuminate\Routing\Controller空类
使用 ValidatesRequests trait
使用 AuthorizesRequests trait
参考:Laravel 10 的 Controller vs Laravel 11 的 Controller替代方案:
// 使用 $request->validate()
public function store(Request $request)
{
    $validated = $request->validate([
        'title' => 'required|string|max:255',
    ]);
}

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

public function update(Request $request, Post $post)
{
    Gate::authorize('update', $post);
}
如果使用频繁,也可以把 App\Http\Controllers\Controller 恢复为 Laravel 10 的样式。
<?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;
}
新结构中 app/Http/Kernel.php 已被废弃,中间件配置改在 bootstrap/app.phpwithMiddleware() 中进行。
// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
    // TrustProxies 等中间件所配置的项目都可以通过 Middleware 类的方法配置
    $middleware->trustProxies(at: '*');

    // 添加全局中间件
    $middleware->append(\App\Http\Middleware\MyMiddleware::class);

    // 为路由组配置别名
    $middleware->alias([
        'my-middleware' => \App\Http\Middleware\MyMiddleware::class,
    ]);

    // 自定义 Web / API 中间件组
    $middleware->web(append: [
        \App\Http\Middleware\HandleInertiaRequests::class,
    ]);
})
自定义中间件文件本身仍然创建在 app/Http/Middleware/ 目录中。
$this->middleware()Illuminate\Routing\Controller 的功能,新结构的空基类 Controller 中不可用。请改为实现 HasMiddleware 接口并定义 middleware() 方法。
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']),
        ];
    }
}
Laravel 13 以后也可以使用 #[Middleware] 属性。
use Illuminate\Routing\Controllers\HasMiddleware;
use App\Http\Middleware\EnsureTokenIsValid;

#[Middleware(EnsureTokenIsValid::class)]
class UserController extends Controller
{
    // ...
}
参考:Controller 中间件
authorizeResource() 依赖 AuthorizesRequests trait,因此在新结构的空基类 Controller 中不可用。有几种应对方式。1. 把基类 Controller 恢复为 Laravel 10 的形式(最简便)
// app/Http/Controllers/Controller.php
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Routing\Controller as BaseController;

abstract class Controller extends BaseController
{
    use AuthorizesRequests;
}
这样就可以使用 $this->authorizeResource()2. 在每个方法上添加 Laravel 13 的 #[Authorize] 属性
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) { /* ... */ }
}
新结构中 app/Console/Kernel.php 已被废弃,Schedule 的配置位置也发生了变化。routes/console.php 中定义(推荐):
// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::command('emails:send')->daily();
Schedule::job(new SendEmails)->everyFiveMinutes();
bootstrap/app.php 中定义:
->withSchedule(function (Schedule $schedule) {
    $schedule->command('emails:send')->daily();
})
新结构废弃了 EventServiceProvider,事件与监听器的手动注册不再必需。自动注册的机制: 只要监听器类的 handle() 方法参数上以类型声明指定了事件类,即可自动注册。
namespace App\Listeners;

use App\Events\OrderShipped;

class SendShipmentNotification
{
    // 只要在 handle() 的参数中指定事件类即可自动注册
    public function handle(OrderShipped $event): void
    {
        // ...
    }
}
如果需要手动注册,可以在 AppServiceProvider::boot() 中处理。
use Illuminate\Support\Facades\Event;

public function boot(): void
{
    Event::listen(
        OrderShipped::class,
        SendShipmentNotification::class,
    );
}
新结构中,ServiceProvider 的清单管理从 config/app.php 迁移到了 bootstrap/providers.php
// bootstrap/providers.php
return [
    App\Providers\AppServiceProvider::class,
    App\Providers\MyCustomServiceProvider::class, // ← 添加到这里
];
使用 artisan make:provider 创建的 Provider 会自动追加到此文件中。
新结构中 app/Exceptions/Handler.php 已被废弃,异常处理的配置改在 bootstrap/app.phpwithExceptions() 中进行。
// bootstrap/app.php
->withExceptions(function (Exceptions $exceptions) {
    // 不上报特定异常
    $exceptions->dontReport(InvalidOrderException::class);

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

    // 修改未认证时的跳转目标
    $exceptions->shouldRenderJsonWhen(function (Request $request, Throwable $e) {
        return $request->is('api/*');
    });
})
路由的自定义在 bootstrap/app.phpwithRouting() 中进行。添加路由文件:
->withRouting(
    web: __DIR__.'/../routes/web.php',
    then: function () {
        Route::middleware('web')
            ->prefix('admin')
            ->group(base_path('routes/admin.php'));
    },
)
完全接管(与 Laravel 10 的 RouteServiceProvider 相同):指定 using 后,Laravel 默认的路由注册将完全被禁用,你可以自行控制所有路由。
->withRouting(
    using: function () {
        Route::middleware('web')
            ->group(base_path('routes/web.php'));

        Route::middleware('api')
            ->prefix('api')
            ->group(base_path('routes/api.php'));
    },
)
config/app.php 添加 providers 键后,会与框架内的 config/app.php 合并生效。
// config/app.php
use Illuminate\Support\ServiceProvider;

return [
    // ...
    'providers' => ServiceProvider::defaultProviders()->replace([
        Illuminate\Foo\FooServiceProvider::class => Bar\BarServiceProvider::class,
    ])->toArray(),
];
通过 replace() 方法可以将默认 Provider 替换为自定义实现。
从 Laravel 11 起,API 功能默认不再包含,如需使用可单独安装。
php artisan install:api
该命令会创建/配置以下内容:
  • routes/api.php
  • 用于 API 认证的 Laravel Sanctum 配置
  • 将 API 路由注册到 bootstrap/app.php
从 Laravel 11 起,广播功能默认也不再包含,如需使用可单独安装。
php artisan install:broadcasting
该命令会创建/配置以下内容:
  • routes/channels.php
  • Laravel Reverb 的安装配置
  • 广播的配置文件
请查看 bootstrap/app.php 的内容。Laravel 11 之后的新结构(或已迁移):
// bootstrap/app.php
return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(...)
    ->withMiddleware(...)
    ->withExceptions(...)
    ->create();
仍以 Laravel 10 之前的旧结构升级的项目:
// 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
);
// ...
形如 return Application::configure(... 就是新结构,否则就是仍以旧结构升级的项目。将旧结构项目迁移到新结构的步骤请参考迁移指南

相关页面

Laravel 11 之后的应用结构

详细讲解新应用结构的全貌以及 ApplicationBuilder 的内部实现。

旧结构到新结构的迁移指南

讲解从 Laravel 10 的旧应用结构迁移到 Laravel 11 之后新结构的步骤。
最后修改于 2026年7月13日