Skip to content

升级指南

高影响变更

中等影响变更

低影响变更

从 12.x 升级到 13.0

预计升级时间:10 分钟

NOTE

我们尝试记录每一个可能的破坏性变更。由于其中一些破坏性变更仅存在于框架的冷门部分,因此实际上只有部分变更会影响您的应用程序。为了节省时间,您可以使用 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 更新安装器:

shell
composer global update laravel/installer

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

缓存

影响可能性:低

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

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

如果您的应用程序依赖这些生成的默认值,升级后缓存键和会话 cookie 名称可能会更改:

php
// 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::snake((string) env('APP_NAME', 'laravel')).'_session';

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

StoreRepository 契约:touch

影响可能性:极低

缓存契约现在包含用于扩展项目 TTL 的 touch 方法。如果您维护自定义缓存存储实现,则应添加此方法:

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

缓存 serializable_classes 配置

影响可能性:中等

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

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

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

容器

Container::call 和可空类默认值

影响可能性:低

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

php
$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 带 JOINORDER BYLIMITDELETE 查询

影响可能性:低

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

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

Eloquent

模型引导和嵌套实例化

影响可能性:极低

在模型仍在引导时创建新模型实例现在被禁止,并抛出 LogicException

这影响从模型 boot 方法或 trait boot* 方法内部实例化模型的代码:

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

    // 在引导期间不再允许...
    (new static())->getTable();
}

将此逻辑移到引导周期之外以避免嵌套引导。

多态中间表名称生成

影响可能性:低

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

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

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

影响可能性:低

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

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

HTTP 客户端

HTTP 客户端 Response::throwthrowIf 签名

影响可能性:极低

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

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

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

通知

默认密码重置主题

影响可能性:极低

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

text
// Laravel <= 12.x
Reset Password Notification

// Laravel >= 13.x
Reset your password

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

队列通知和缺失模型

影响可能性:极低

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

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

队列

JobAttempted 事件异常负载

影响可能性:低

Illuminate\Queue\Events\JobAttempted 事件现在通过 $exception 公开异常对象(或 null),替换以前的布尔 $exceptionOccurred 属性:

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

// Laravel >= 13.x
$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,特别是在测试或路由定义中排除中间件时:

php
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),请更新您的期望。

视图

分页 Bootstrap 视图名称

影响可能性:低

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

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

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

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

其他

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