升级指南

未匹配的标注
本文档最新版为 12.x,旧版本可能放弃维护,推荐阅读最新版!

升级指南

  • 从 12.x 升级到 13.0
    • 利用人工智能进行升级

高影响变更

  • 更新依赖项
  • 更新 Laravel 安装程序
  • 请求伪造防护

中等影响变更

  • 缓存 serializable_classes 配置项
  • 在 MySQL 或 MariaDB 中使用数据库的 upsert 方法

低影响变更

  • 缓存前缀与会话 Cookie 名称
  • 集合模型序列化恢复预加载关联
  • Container::call 与可空类默认值
  • 域名路由注册优先级
  • JobAttempted 事件异常负载
  • 管理器的 extend 回调绑定
  • 支持使用 JOIN、ORDER BY 和 LIMIT 执行 DELETE 操作
  • 分页 Bootstrap 视图名称
  • 多态中间表名称生成规则
  • QueueBusy 事件属性重命名
  • 测试中自动重置 Str Factories

从 12.x 升级到 13.0

预计升级时间:10 分钟

[!NOTE]
我们尝试记录每一个可能的重大变更。由于这些变更中的一些位于框架的偏僻部分,只有一部分变更可能实际影响您的应用程序。想节省时间吗?您可以使用 Laravel Shift 来帮助自动化您的应用程序升级。Shift 是一个由社区维护的服务,可以自动化完成 Laravel 的升级过程。

使用 AI 进行升级

您可以使用 Laravel Boost 来完成自动化升级。 Boost 是一个官方 MCP 服务器,旨在为您的 AI 助手提供引导式升级提示 —— 将它安装到任意 Laravel 12 应用后,在 Claude Code、Cursor、OpenCode、Gemini 或 VS Code 中使用 /upgrade-laravel-v13 命令,即可开始升级至 Laravel 13。该命令要求 Laravel Boost 版本为 ^2.0。

更新依赖项

影响可能性:高

您需要在应用的 composer.json 文件中更新以下依赖项:

  • laravel/framework 更新至 ^13.0
  • laravel/boost 更新至 ^2.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 进行更新:

composer global update laravel/installer

或者,如果您使用的是 Laravel Herd 附带的 Laravel 安装器,请将 Herd 更新至最新的版本。

缓存

缓存前缀与会话 Cookie 名称

影响可能性:低

Laravel 默认的缓存和 Redis 键前缀现在使用连字符后缀。

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

// Laravel <= 12.x
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_cache_';
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_database_';
Str::slug((string) env('APP_NAME', 'laravel'), '_').'_session';

// Laravel >= 13.x
Str::slug((string) env('APP_NAME', 'laravel')).'-cache-';
Str::slug((string) env('APP_NAME', 'laravel')).'-database-';
Str::slug((string) env('APP_NAME', 'laravel')).'-session';

要保留先前的行为,请在环境中显式配置 CACHE_PREFIXREDIS_PREFIX 和 SESSION_COOKIE

Store 和 Repository 契约:touch

影响可能性:极低

缓存契约现在包含一个用于延长项 TTL(生存时间)的 touch 方法。如果您维护了自定义的缓存存储实现,请添加此方法:

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

缓存 serializable_classes 配置

影响可能性:中等

默认应用的 cache 配置现在包含一个设置为 falseserializable_classes 选项。此配置增强了缓存反序列化行为的安全性,有助于在您的应用的 APP_KEY 泄露时防止 PHP 反序列化利用链攻击。如果您的应用有意在缓存中存储 PHP 对象,则应显式列出允许反序列化的类:

'serializable_classes' => [
    App\Data\CachedDashboardStats::class,
    App\Support\CachedPricingSnapshot::class,
],

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

容器

Container::call 和可为空类默认值

影响可能性:低

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

$container->call(function (?Carbon $date = null) {
    return $date;
});

// Laravel <= 12.x: Carbon 实例
// Laravel >= 13.x: null

如果你的方法调用注入逻辑依赖于先前行为,则可能需要更新它。

契约

Dispatcher 契约:dispatchAfterResponse

影响可能性:极低

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

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

ResponseFactory 契约:eventStream

影响可能性:极低

Illuminate\Contracts\Routing\ResponseFactory 契约现在包含了一个 eventStream 方法签名。

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

MustVerifyEmail 契约:markEmailAsUnverified

影响可能性:极低

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

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

数据库

使用 MySQL 或 MariaDB 进行数据库 upsert 操作

影响可能性:中等

Laravel 现在会验证调用方是否提供了非空的 uniqueBy 值,并在值为空时抛出 InvalidArgumentException,而不是生成无效的 SQL 语句。

尽管 MariaDB 和 MySQL 数据库驱动会忽略 uniqueBy 值并始终使用表的主键和唯一索引来检测已存在的记录,但验证规则依然适用。如果 uniqueBy 为空,将抛出 InvalidArgumentException

带有 JOINORDER BY 和 LIMIT 的 MySQL DELETE 查询

影响可能性:低

Laravel 现在会在 MySQL 语法中完整编译包含 ORDER BYLIMITDELETE ... JOIN 查询。

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

Eloquent

模型启动与嵌套实例化

影响可能性:极低

现在,在模型仍在启动过程中创建新的模型实例将被禁止,并会抛出 LogicException

这会影响在模型 boot 方法或 trait boot* 方法中实例化模型的代码:

protected static function boot()
{
    parent::boot();

    // 启动期间不再允许这样做...
    (new static())->getTable();
}

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

多态中间表名称生成

影响可能性:低

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

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

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

影响可能性:低

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

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

HTTP 客户端

HTTP 客户端 Response::throw 与 throwIf 方法签名

影响可能性:极低

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

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

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

通知

默认密码重置邮件主题

影响可能性:极低

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

// Laravel <= 12.x
重置密码通知

// Laravel >= 13.x
重置您的密码

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

队列通知与缺失模型

影响可能性:极低

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

在先前版本中,在你期望它们被删除的情况下,缺失模型仍可能导致队列通知任务失败。

队列

JobAttempted 事件异常负载

影响可能性:低

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

// Laravel <= 12.x
$event->exceptionOccurred;

// Laravel >= 13.x
$event->exception;

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

QueueBusy 事件属性重命名

影响可能性:低

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

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

Queue 契约方法添加

影响可能性:极低

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

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

  • pendingSize
  • delayedSize
  • reservedSize
  • creationTimeOfOldestPendingJob

路由

域名路由注册优先级

影响可能性:低

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

这使得即使非域名路由更早注册,通配子域名路由能够保持一致的行为。如果您的应用依赖于域名路由与非域名路由之间原有的注册优先级,请检查路由匹配行为。

任务调度

withScheduling 注册时机

影响可能性:极低

通过 ApplicationBuilder::withScheduling() 注册的调度任务现在会延迟到 Schedule 被解析时才执行。

如果您的应用依赖于在引导阶段立即执行调度注册,您可能需要调整相关逻辑。

安全

请求伪造保护

影响可能性:高

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

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

use Illuminate\Foundation\Http\Middleware\PreventRequestForgery;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;

// Laravel <= 12.x
->withoutMiddleware([VerifyCsrfToken::class]);

// Laravel >= 13.x
->withoutMiddleware([PreventRequestForgery::class]);

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

支持

管理器 extend 回调绑定

影响可能性:低

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

如果您之前在这些回调中依赖于另一个绑定对象(例如服务提供者实例)作为这些回调中的 $this,您应将这些值通过 use (...) 语法捕获到闭包中。

测试间重置 Str 工厂

影响可能性:低

Laravel 现在在测试拆卸(teardown)时会重置自定义的 Str 工厂。

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

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

影响可能性:极低

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

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

工具类

Symfony PHP 8.5 Polyfill 与全局函数冲突

影响可能性:低

Laravel 13 引入了对 symfony/polyfill-php85 的依赖。在低于 PHP 8.5 的版本上,此 Polyfill 会定义诸如 array_first()array_last() 等全局函数——除非这些函数已经在引导过程中更早地定义过。

这些函数可能与传统的辅助函数包(如 laravel/helpers)或使用相同名称的自定义全局辅助函数产生冲突。例如,历史版本的 array_first() 辅助函数接受一个回调以返回第一个匹配的元素,而 Polyfill 版本仅返回数组的第一个元素。

为避免冲突并确保在不同 PHP 版本间行为一致,您应优先使用 Illuminate\Support\Arr 方法:

use Illuminate\Support\Arr;

Arr::first($array, function ($value) {
  return /* 条件 */;
});

视图

分页 Bootstrap 视图名称

影响可能性:低

Bootstrap 3 默认的内部分页视图名称现在已明确:

// Laravel <= 12.x
pagination::default
pagination::simple-default

// Laravel >= 13.x
pagination::bootstrap-3
pagination::simple-bootstrap-3

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

其他事项

我们还建议您查看 laravel/laravelGitHub 仓库 中的变更。虽然许多更改并非必须,但您可能希望将这些文件与您的应用保持同步。其中一些更改已在本升级指南中涵盖,而其他更改(例如配置文件或注释的更新)则未提及。您可以使用 GitHub 比较工具 轻松查看变更,并选择对您重要的更新。

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/laravel/13.x/up...

译文地址:https://learnku.com/docs/laravel/13.x/up...

上一篇 下一篇
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
贡献者:3
讨论数量: 0
发起讨论 只看当前版本


暂无话题~