升级指南
高影响变更
中等影响变更
低影响变更
- 缓存前缀与会话 Cookie 名称
- 集合模型序列化会恢复预加载关联
Container::call与可空类默认值- 域名路由注册优先级
JobAttempted事件异常载荷- Manager
extend回调绑定 - 带
JOIN、ORDER BY与LIMIT的 MySQLDELETE查询 - 分页 Bootstrap 视图名称
- 多态中间表名称生成
QueueBusy事件属性重命名- 会话
serialization配置 Str工厂在测试间重置
从 12.x 升级到 13.0
预计升级时间:10 分钟
INFO
我们尽量记录每一处可能的破坏性变更。由于部分变更位于框架较冷门的区域,其中只有一部分可能真正影响你的应用。为节省时间,可使用 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/frameworkto^13.0laravel/boostto^2.0laravel/tinkerto^3.0phpunit/phpunitto^12.0pestphp/pestto^4.0
更新 Laravel 安装器
若使用 Laravel 安装器 CLI 创建新应用,应更新安装器以兼容 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
影响可能性:极低
缓存契约现在包含用于延长缓存项 TTL 的 touch 方法。若维护自定义缓存存储实现,应添加该方法:
// 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 查询。
在先前版本中,带 JOIN 的删除上 ORDER BY / LIMIT 子句可能被静默忽略。在 Laravel 13 中,这些子句会包含在生成的 SQL 中。因此,不支持该语法的数据库引擎(例如标准 MySQL / MariaDB 变体)现在可能抛出 QueryException,而不是执行无界删除。
Eloquent
模型启动与嵌套实例化
影响可能性:极低
在模型仍在启动时创建新模型实例现已禁止,并会抛出 LogicException。
这会影响在模型 boot 方法或 trait 的 boot* 方法中实例化模型的代码:
protected static function boot()
{
parent::boot();
// No longer allowed during booting...
(new static())->getTable();
}请将此类逻辑移出启动周期,以避免嵌套启动。
多态中间表名称生成
影响可能性:低
当使用自定义中间模型类为多态中间模型推断表名时,Laravel 现在会生成复数形式的名称。
若应用依赖先前为 morph 中间表推断的单数名称,并且使用了自定义中间类,应在中间模型上显式定义表名。
集合模型序列化会恢复预加载关联
影响可能性:低
当 Eloquent 模型集合被序列化并恢复时(例如在队列任务中),现在会为集合中的模型恢复预加载关联。
若代码依赖反序列化后关联不存在,可能需要调整该逻辑。
HTTP 客户端
HTTP 客户端 Response::throw 与 throwIf 签名
影响可能性:极低
HTTP 客户端响应方法现在在方法签名中声明回调参数:
public function throw($callback = null);
public function throwIf($condition, $callback = null);若在自定义响应类中重写这些方法,请确保方法签名兼容。
通知
默认密码重置主题
影响可能性:极低
Laravel 默认密码重置邮件主题已更改:
// Laravel <= 12.x
Reset Password Notification
// Laravel >= 13.x
Reset your password若测试、断言或翻译覆盖依赖先前的默认字符串,请相应更新。
队列通知与缺失模型
影响可能性:极低
队列通知现在会尊重通知类上定义的 #[DeleteWhenMissingModels] attribute 与 $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(...)。
支持类
Manager extend 回调绑定
影响可能性:低
通过 manager 的 extend 方法注册的自定义驱动闭包现在会绑定到 manager 实例。
若此前依赖其他绑定对象(例如服务提供者实例)作为这些回调中的 $this,应使用 use (...) 将这些值捕获进闭包。
Str 工厂在测试间重置
影响可能性:低
Laravel 现在会在测试拆除阶段重置自定义 Str 工厂。
若测试依赖自定义 UUID / ULID / 随机字符串工厂在测试方法之间保持,应在每个相关测试或 setup 钩子中重新设置。
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若应用直接引用旧的分页视图名称,请更新这些引用。
其他
我们也鼓励你查看 laravel/laravel GitHub 仓库 中的变更。其中许多变更并非必需,但你可能希望让这些文件与应用保持同步。本升级指南会涵盖部分变更,但配置文件或注释等其他变更不会。你可使用 GitHub 比较工具 轻松查看变更,并选择对你重要的更新。