高影响变更
- 更新依赖项
- 更新 Laravel 安装器
- 请求伪造防护
中影响变更
- 缓存
serializable_classes配置 - 使用 MySQL 或 MariaDB 的数据库
upsert
低影响变更
- 缓存前缀与会话 Cookie 名称
- 集合模型序列化还原预加载关系
Container::call与可空类默认值- 域路由注册优先级
JobAttempted事件异常载荷- Manager
extend回调绑定 - 带有
JOIN、ORDER BY和LIMIT的 MySQLDELETE查询 - 分页 Bootstrap 视图名称
- 多态中间表名称生成
QueueBusy事件属性重命名- 会话
serialization配置 - 测试间重置
Str工厂
从 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。该命令需要 Laravel Boost ^2.0。
更新依赖项
影响可能性:高
您应在应用的 composer.json 文件中更新以下依赖项:
laravel/framework到^13.0laravel/boost到^2.0laravel/tinker到^3.0phpunit/phpunit到^12.0pestphp/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 键前缀现在使用带连字符的后缀。
在大多数应用中,此变更不会生效,因为应用级配置文件已经定义了这些值。该变更主要影响在对应应用配置值不存在时、依赖框架级回退配置的应用。
如果您的应用依赖这些生成的默认值,升级后缓存键与会话 Cookie 名称可能会发生变化:
// 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_PREFIX、REDIS_PREFIX 和 SESSION_COOKIE。
Store 与 Repository 契约:touch
影响可能性:极低
缓存契约现在包含一个 touch 方法,用于延长条目的 TTL。如果您维护自定义缓存存储实现,应添加此方法:
// Illuminate\Contracts\Cache\Store
public function touch($key, $seconds);缓存 serializable_classes 配置
影响可能性:中
默认应用 cache 配置现在包含一个设置为 false 的 serializable_classes 选项。这会加强缓存反序列化行为,以便在您的应用 APP_KEY 泄露时帮助防止 PHP 反序列化 gadget 链攻击。如果您的应用有意将 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 instance
// Laravel >= 13.x: null如果您的方法调用注入逻辑依赖之前的行为,可能需要进行更新。
契约
Dispatcher 契约:dispatchAfterResponse
影响可能性:极低
Illuminate\Contracts\Bus\Dispatcher 契约现在包含 dispatchAfterResponse($command, $handler = null) 方法。
如果您维护自定义 dispatcher 实现,请在类中添加此方法。
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。
带有 JOIN、ORDER BY 和 LIMIT 的 MySQL DELETE 查询
影响可能性:低
Laravel 现在会为 MySQL 语法编译包含 ORDER BY 和 LIMIT 的完整 DELETE ... JOIN 查询。
在之前的版本中,在带连接的删除操作中,ORDER BY / LIMIT 子句可能会被静默忽略。在 Laravel 13 中,这些子句会被包含在生成的 SQL 中。因此,不支持此语法的数据库引擎(MySQL,以及 11.8.1 之前的 MariaDB)现在可能会抛出 QueryException,而不是执行无限制删除。
Eloquent
模型引导与嵌套实例化
影响可能性:极低
在模型仍在引导时创建新的模型实例现已被禁止,并会抛出 LogicException。
这会影响从模型 boot 方法或 trait boot* 方法内部实例化模型的代码:
protected static function boot()
{
parent::boot();
// No longer allowed during booting...
(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 契约现在包含了此前仅在文档注释中声明的队列大小检查方法。
如果你维护该契约的自定义队列驱动实现,请添加以下方法的实现:
pendingSizedelayedSizereservedSizecreationTimeOfOldestPendingJob
路由
域名路由注册优先级
影响可能性:低
在路由匹配中,带有显式域名的路由现在优先于非域名路由。
这使得全匹配子域名路由即使在非域名路由更早注册的情况下,也能保持一致的行为。如果你的应用依赖此前域名路由与非域名路由之间的注册优先级,请审查路由匹配行为。
会话
会话 serialization 配置
影响可能性:低
为了帮助防止 PHP 反序列化 gadget 链攻击,默认应用骨架现在在 config/session.php 文件中将会话 serialization 选项设置为 json。
如果你正在升级现有应用并同步配置文件到 Laravel 13 骨架,将此值从 php 更新为 json 会导致所有活跃的用户会话失效。
如果你希望在升级过程中无缝保持活跃会话,应确保此值保持为 php。不过,如果你的应用不在会话中存储 PHP 对象,并且你愿意要求用户重新验证身份,我们建议将此值更新为 json,以提高安全性。
调度
withScheduling 注册时机
影响可能性:极低
通过 ApplicationBuilder::withScheduling() 注册的调度现在会延迟到 Schedule 被解析时。
如果你的应用依赖引导阶段立即注册调度的时机,可能需要调整相应逻辑。
安全
请求伪造防护
影响可能性:高
Laravel 的 CSRF 中间件已从 VerifyCsrfToken 更名为 PreventRequestForgery,并且现在包含使用 Sec-Fetch-Site 请求头的请求来源验证。
VerifyCsrfToken 和 ValidateCsrfToken 仍作为弃用的别名保留,但应将直接引用更新为 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 现在会在测试销毁阶段重置自定义的 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 的依赖。在低于 8.5 的 PHP 版本上,除非这些全局函数在引导过程中已提前定义,否则该 polyfill 会定义诸如 array_first() 和 array_last() 等全局函数。
这些函数可能会与诸如 laravel/helpers 之类的旧版辅助包或使用相同名称的自定义全局辅助函数产生冲突。例如,历史上的 array_first() 辅助函数接受一个回调以返回第一个匹配的元素,而 polyfill 版本仅返回数组的第一个元素。
为了避免冲突并确保跨 PHP 版本的行为一致,建议优先使用 Illuminate\Support\Arr 的方法:
use Illuminate\Support\Arr;
Arr::first($array, function ($value) {
return /* condition */;
});视图
分页 Bootstrap 视图名称
影响可能性:低
Bootstrap 3 默认设置的内部分页视图名称现在变得更为明确:
// Laravel <= 12.x
pagination::default
pagination::simple-default
// Laravel >= 13.x
pagination::bootstrap-3
pagination::simple-bootstrap-3如果你的应用直接引用了旧的分页视图名称,请更新这些引用。
其他
我们也建议你查看 GitHub 仓库中 laravel/laravel 的变更。虽然其中许多变更并非必需,但你可能需要让这些文件与你的应用保持同步。本升级指南会涵盖其中部分变更,但其他变更(如配置文件或注释的更改)则不会涵盖。你可以使用GitHub 对比工具轻松查看这些变更,并选择对你而言重要的更新。