跳转至内容

升级指南

高影响变更

中等影响变更

低影响变更

从 12.x 升级至 13.0

预计升级时间:10 分钟

我们尽量记录了所有可能的破坏性变更。由于其中一些变更位于框架的边缘部分,因此只有一部分可能会影响您的应用程序。为了节省时间,您可以使用 Shift。Shift 是一个由社区维护的服务,可自动完成 Laravel 升级。

使用 AI 升级

您可以使用 Laravel Boost 自动升级。Boost 是一个官方的 MCP 服务器,可为您的 AI 助手提供引导式升级提示——一旦安装在任何 Laravel 12 应用程序中,只需在 Claude Code、Cursor、OpenCode、Gemini 或 VS Code 中使用 /upgrade-laravel-v13 斜杠命令,即可开始升级到 Laravel 13。

更新依赖

影响可能性:高

您应该更新应用程序 composer.json 文件中的以下依赖项:

  • laravel/framework 更新为 ^13.0
  • laravel/tinker 更新为 ^3.0
  • phpunit/phpunit 更新为 ^12.0
  • pestphp/pest 更新为 ^4.0

更新 Laravel 安装程序

如果您使用 Laravel 安装程序 CLI 工具来创建新的 Laravel 应用程序,则应更新您的安装程序以保持与 Laravel 13.x 的兼容性。

如果您通过 composer global require 安装了 Laravel 安装程序,则可以使用 composer global update 更新它。

1composer global update laravel/installer

或者,如果您使用的是 Laravel Herd 捆绑的 Laravel 安装程序,则应将 Herd 更新到最新版本。

缓存

影响可能性:低

Laravel 的默认缓存和 Redis 键前缀现在使用连字符后缀。此外,默认的会话 Cookie 名称现在使用 Str::snake(...) 来处理应用程序名称。

在大多数应用程序中,此更改不会产生影响,因为应用程序级的配置文件已经定义了这些值。这主要影响那些在缺少相应应用程序配置值时依赖框架级回退配置的应用程序。

如果您的应用程序依赖于这些自动生成的默认值,升级后缓存键和会话 Cookie 名称可能会发生变化。

1// Laravel <= 12.x
2Str::slug((string) env('APP_NAME', 'laravel'), '_').'_cache_';
3Str::slug((string) env('APP_NAME', 'laravel'), '_').'_database_';
4Str::slug((string) env('APP_NAME', 'laravel'), '_').'_session';
5 
6// Laravel >= 13.x
7Str::slug((string) env('APP_NAME', 'laravel')).'-cache-';
8Str::slug((string) env('APP_NAME', 'laravel')).'-database-';
9Str::snake((string) env('APP_NAME', 'laravel')).'_session';

要保留以前的行为,请在您的环境中显式配置 CACHE_PREFIXREDIS_PREFIXSESSION_COOKIE

StoreRepository 契约:touch

影响可能性:非常低

缓存契约现在包含一个用于扩展项目 TTL 的 touch 方法。如果您维护自定义的缓存驱动实现,则需要添加此方法。

1// Illuminate\Contracts\Cache\Store
2public function touch($key, $seconds);

缓存 serializable_classes 配置

影响可能性:中

默认的应用程序 cache 配置现在包含一个设置为 falseserializable_classes 选项。这强化了缓存反序列化行为,如果您的 APP_KEY 被泄露,有助于防止 PHP 反序列化小工具链攻击。如果您的应用程序有意在缓存中存储 PHP 对象,您应该显式列出可以反序列化的类。

1'serializable_classes' => [
2 App\Data\CachedDashboardStats::class,
3 App\Support\CachedPricingSnapshot::class,
4],

如果您的应用程序之前依赖于反序列化任意缓存对象,则需要将该用法迁移到显式的类白名单,或迁移到非对象缓存负载(例如数组)。

容器

Container::call 与可空类默认值

影响可能性:低

Container::call 现在在没有绑定存在时尊重可空类参数的默认值,这与 Laravel 12 中引入的构造函数注入行为相匹配。

1$container->call(function (?Carbon $date = null) {
2 return $date;
3});
4 
5// Laravel <= 12.x: Carbon instance
6// Laravel >= 13.x: null

如果您的方法调用注入逻辑依赖于之前的行为,您可能需要对其进行更新。

契约 (Contracts)

Dispatcher 契约:dispatchAfterResponse

影响可能性:非常低

Illuminate\Contracts\Bus\Dispatcher 契约现在包含 dispatchAfterResponse($command, $handler = null) 方法。

如果您维护了自定义的调度器实现,请将此方法添加到您的类中。

ResponseFactory 契约:eventStream

影响可能性:非常低

Illuminate\Contracts\Routing\ResponseFactory 契约现在包含 eventStream 签名。

如果您维护了此契约的自定义实现,则应添加此方法。

MustVerifyEmail 契约:markEmailAsUnverified

影响可能性:非常低

Illuminate\Contracts\Auth\MustVerifyEmail 契约现在包含 markEmailAsUnverified()

如果您提供了此契约的自定义实现,请添加此方法以保持兼容性。

数据库

带有 JOIN, ORDER BYLIMIT 的 MySQL DELETE 查询

影响可能性:低

Laravel 现在为 MySQL 语法编译完整的 DELETE ... JOIN 查询,包括 ORDER BYLIMIT

在以前的版本中,ORDER BY / LIMIT 子句在连接删除操作中可能会被静默忽略。在 Laravel 13 中,这些子句被包含在生成的 SQL 中。因此,不支持此语法的数据库引擎(如标准 MySQL / MariaDB 变体)现在可能会抛出 QueryException,而不是执行无限制的删除。

Eloquent

模型启动与嵌套实例化

影响可能性:非常低

现在禁止在模型启动期间创建新的模型实例,这会抛出 LogicException

这会影响在模型 boot 方法或 trait boot* 方法内部实例化模型的代码。

1protected static function boot()
2{
3 parent::boot();
4 
5 // No longer allowed during booting...
6 (new static())->getTable();
7}

请将此逻辑移出启动周期,以避免嵌套启动。

多态中间表名称生成

影响可能性:低

当为使用自定义中间表模型的对象使用多态表名推断时,Laravel 现在会生成复数名称。

如果您的应用程序依赖于之前用于多态中间表的单数推断名称,并且使用了自定义中间表类,则应在中间表模型上显式定义表名。

集合模型序列化恢复预加载关联

影响可能性:低

当 Eloquent 模型集合被序列化和恢复(例如在队列任务中)时,现在会为集合中的模型恢复预加载的关联。

如果您的代码依赖于反序列化后关联不存在的状态,您可能需要调整该逻辑。

HTTP 客户端

HTTP 客户端 Response::throwthrowIf 签名

影响可能性:非常低

HTTP 客户端响应方法现在在其方法签名中声明了回调参数。

1public function throw($callback = null);
2public function throwIf($condition, $callback = null);

如果您在自定义响应类中重写了这些方法,请确保您的方法签名是兼容的。

通知

默认密码重置主题

影响可能性:非常低

Laravel 的默认密码重置邮件主题已更改。

1// Laravel <= 12.x
2Reset Password Notification
3
4// Laravel >= 13.x
5Reset your password

如果您的测试、断言或翻译覆盖依赖于之前的默认字符串,请相应地更新它们。

队列通知与缺失模型

影响可能性:非常低

队列通知现在尊重通知类上定义的 #[DeleteWhenMissingModels] 属性和 $deleteWhenMissingModels 属性。

在以前的版本中,即使在您预期删除它们的情况下,缺失的模型仍可能导致队列通知任务失败。

队列

JobAttempted 事件异常负载

影响可能性:低

Illuminate\Queue\Events\JobAttempted 事件现在通过 $exception 属性公开异常对象(或 null),取代了之前的布尔值 $exceptionOccurred 属性。

1// Laravel <= 12.x
2$event->exceptionOccurred;
3 
4// Laravel >= 13.x
5$event->exception;

如果您正在监听此事件,请相应地更新监听器代码。

QueueBusy 事件属性重命名

影响可能性:低

Illuminate\Queue\Events\QueueBusy 事件的 $connection 属性已重命名为 $connectionName,以与其他队列事件保持一致。

如果您的监听器引用了 $connection,请将其更新为 $connectionName

Queue 契约方法补充

影响可能性:非常低

Illuminate\Contracts\Queue\Queue 契约现在包含了以前仅在文档块中声明的队列大小检查方法。

如果您维护了此契约的自定义队列驱动实现,请添加以下方法的实现:

  • pendingSize
  • delayedSize
  • reservedSize
  • creationTimeOfOldestPendingJob

路由

域名路由注册优先级

影响可能性:低

在路由匹配中,具有显式域名的路由现在优先于非域名路由。

即使非域名路由注册得更早,这也允许全匹配子域名路由保持一致的行为。如果您的应用程序依赖于之前域名和非域名路由之间的注册优先级,请审查路由匹配行为。

调度

withScheduling 注册时机

影响可能性:非常低

通过 ApplicationBuilder::withScheduling() 注册的计划现在会推迟到 Schedule 解析时执行。

如果您的应用程序依赖于引导期间的即时计划注册时机,您可能需要调整该逻辑。

安全

请求伪造保护

影响可能性:高

Laravel 的 CSRF 中间件已从 VerifyCsrfToken 重命名为 PreventRequestForgery,并且现在使用 Sec-Fetch-Site 请求头包含请求源验证。

VerifyCsrfTokenValidateCsrfToken 仍然作为弃用的别名保留,但应将直接引用更新为 PreventRequestForgery,特别是在测试或路由定义中排除中间件时。

1use Illuminate\Foundation\Http\Middleware\PreventRequestForgery;
2use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
3 
4// Laravel <= 12.x
5->withoutMiddleware([VerifyCsrfToken::class]);
6 
7// Laravel >= 13.x
8->withoutMiddleware([PreventRequestForgery::class]);

中间件配置 API 现在也提供了 preventRequestForgery(...) 方法。

支持

管理器 extend 回调绑定

影响可能性:低

通过管理器 extend 方法注册的自定义驱动闭包现在绑定到管理器实例上。

如果您之前在这些回调内部将其他绑定对象(如服务提供者实例)作为 $this 使用,则应使用 use (...) 将这些值移至闭包捕获中。

Str 工厂在测试间重置

影响可能性:低

Laravel 现在在测试结束时重置自定义的 Str 工厂。

如果您的测试依赖于自定义 UUID / ULID / 随机字符串工厂在测试方法间保持持久性,则应在每个相关测试或设置钩子中重新设置它们。

Js::from 默认使用未转义的 Unicode

影响可能性:非常低

Illuminate\Support\Js::from 现在默认使用 JSON_UNESCAPED_UNICODE

如果您的测试或前端输出比较依赖于转义的 Unicode 序列(例如 \u00e8),请更新您的预期结果。

视图

分页 Bootstrap 视图名称

影响可能性:低

Bootstrap 3 默认设置的内部分页视图名称现在更加明确。

1// Laravel <= 12.x
2pagination::default
3pagination::simple-default
4
5// Laravel >= 13.x
6pagination::bootstrap-3
7pagination::simple-bootstrap-3

如果您的应用程序直接引用了旧的分页视图名称,请更新这些引用。

其他

我们还鼓励您查看 laravel/laravel GitHub 仓库中的更改。虽然许多更改并非强制要求,但您可能希望保持这些文件与您的应用程序同步。其中一些更改将包含在本升级指南中,但其他更改(例如配置文件或注释的更改)则不会。您可以通过 GitHub 比较工具轻松查看更改,并选择对您重要的更新。