跳转到主要内容

与 Laravel 10 及之前的对比

Laravel 11 以「Slim Application Skeleton」为名,对应用结构进行了大规模改造。最大的变化是消除了配置的分散,将其汇总到 bootstrap/app.php 一个位置。
该变更面向新项目。已有的 Laravel 10 应用即使升级到新版本,旧结构仍可继续正常运行。

新的目录与文件结构

Skeleton 的目录构成

bootstrap/app.php — 应用配置的中心

仅通过这一个文件,就可以配置路由、中间件与异常处理。Laravel 10 及之前分散在 app/Http/Kernel.phpapp/Console/Kernel.phpapp/Exceptions/Handler.php 三处的配置,都被汇总到这里。

bootstrap/providers.php — Service Provider 列表

该文件是 Service Provider 的注册位置。Laravel 10 中在 config/app.phpproviders 数组里定义,现在被分离到了 bootstrap/providers.php。Laravel 11 的默认内容只有 AppServiceProvider
通过 composer require 安装包时,该包可能会自动更新 bootstrap/providers.phpconfig/app.php 并非不再被引用,但新增注册的推荐位置已变为 bootstrap/providers.php

routes/ 目录的变化

api.phpchannels.php 默认不存在。有需要时可以用 Artisan 命令生成。
routes/console.php 中也可以定义计划任务。

被废弃的文件

HTTP Kernel 被整合进框架内部的 Illuminate\Foundation\Http\Kernel。中间件的自定义在 bootstrap/app.phpwithMiddleware() 中完成。
Console Kernel 的两项职责被拆分。Artisan 命令放在 app/Console/Commands/ 中会被自动发现,计划任务写在 routes/console.php 中。
异常处理器被整合进框架内部的 Illuminate\Foundation\Exceptions\Handler。自定义在 bootstrap/app.phpwithExceptions() 中完成。

Application::configure() 的机制

框架内部的实现

Application::configure()Illuminate\Foundation\Application 上的静态方法。
该方法执行了以下处理:
  1. basePath 确定应用根目录
  2. 创建 Application 实例
  3. ApplicationBuilder 包装并应用默认配置
  4. 返回 ApplicationBuilder 实例
关键在于,configure() 内部已经调用了 withKernels() / withEvents() / withCommands() / withProviders()。你不需要在 bootstrap/app.php 中再次调用这些方法。

通过链式方法进行配置

调用 create() 时会从 ApplicationBuilder 取出 Application 实例,bootstrap/app.php 最终 return 的正是这个 Application 实例。

请求到应用启动的流程

public/index.php 是入口,读取 bootstrap/app.php 获得 Application。之后 HTTP Kernel 将请求送入中间件管道,路由分发到 Controller。

ApplicationBuilder 主要方法深入

withRouting() — 路由注册的内部处理

内部通过 AppRouteServiceProvider::loadRoutesUsing() 注册回调,并在应用 booting 时注册 AppRouteServiceProvider
要点:
  • api 路由会自动应用 api 中间件组与 /api 前缀
  • health 传入字符串会自动注册健康检查端点(默认 /up
  • health 路径在维护模式下也会被排除(通过 PreventRequestsDuringMaintenance::except() 配置)
  • 注意 api 会先于 web 注册。若同一路径同时定义了 Web 和 API 路由,API 路由会优先匹配
  • pages 传入字符串会启用 Laravel Folio 的路由

withMiddleware() — 中间件自定义

withMiddleware()HttpKernel 被解析之后执行回调,这是因为使用了 afterResolving() 钩子。传给回调的 Middleware 对象提供了丰富的自定义方法。

withExceptions() — 异常处理的配置

withExceptions() 首先将框架的 Handler 类作为单例注册,然后通过 afterResolving() 挂接回调。回调会收到一个 Exceptions 包装对象。

withProviders() — Service Provider 注册

由于 withProviders() 已在 Application::configure() 中被默认调用,bootstrap/providers.php 会自动加载。如需追加额外 Provider,需在 bootstrap/app.php 中显式调用。
若传入 withBootstrapProviders: false,将不再加载 bootstrap/providers.php。除非有特殊理由,否则请省略该参数。

其他主要方法

设计意图:为何这样设计

「代码优先」的配置

Laravel 10 及之前的 app/Http/Kernel.php 采用以数组列举中间件的写法。这种写法接近配置文件,但难以享受 PHP 的类型系统与 IDE 支持。 Laravel 11 改为 withMiddleware(function (Middleware $middleware) { ... }) 这样的回调风格。这样能获得类型补全,也可以自然地使用条件分支、循环等逻辑进行动态配置。

从「约定优于配置」到「显式配置」

api.php 改为 opt-in,是为了避免应用不使用 API 路由时仍然始终加载 api 中间件组的问题。方针是:默认不存在未使用的功能。

afterResolving() 钩子的活用

withMiddleware()withExceptions() 使用 afterResolving() 是为了避免配置顺序的问题。ApplicationBuilder 的方法在应用完全启动之前被调用,而实际处理(对 Kernel 应用配置)延迟到 Kernel 第一次被解析时执行。

自定义示例

API 与 Web 共存

中间件的自定义

将计划任务统一到 bootstrap/app.php

计划任务可以写在 routes/console.php 中,也可以用 withSchedule() 统一放到 bootstrap/app.php

异常处理的自定义

bootstrap/app.php 中管理容器绑定

对小型应用,简单的绑定也可以写在 bootstrap/app.php 而非 AppServiceProvider 中。

Laravel 启动流程的顺序

Laravel 应用启动时,Service Provider 与 Application 的钩子按以下顺序执行。
  1. 所有 ServiceProvider 的 register() 执行
  2. Application 的 registered()
  3. Application 的 booting()
  4. 所有 ServiceProvider 的 boot() 执行
  5. Application 的 booted()
AppServiceProvider 中添加以下代码即可确认执行顺序。
ApplicationBuilder 上的 registered()booting()booted() 只是向 Application 注册回调的方法。通常无需使用,但可用于在启动准备完成的 Kernel 上通过 booted() 进行特殊变更。

下一步

服务容器

理解 ApplicationBuilder 内部所使用的服务容器机制。

新应用结构 FAQ

汇总关于新应用结构的常见问题与解答。
最后修改于 2026年7月18日