Skip to content
全部文档

升级指南

高影响变更

中等影响变更

低影响变更

从 11.x 升级到 12.0

预计升级时间:5 分钟

INFO

我们尽量记录每一处可能的破坏性变更。由于部分变更位于框架较冷门的区域,其中只有一部分可能真正影响你的应用。想节省时间?可使用 Laravel Shift 协助自动化升级。

更新依赖

影响可能性:高

应在应用的 composer.json 中更新下列依赖:

  • laravel/framework to ^12.0
  • phpunit/phpunit to ^11.0
  • pestphp/pest to ^3.0

Carbon 3

影响可能性:低

已移除对 Carbon 2.x 的支持。所有 Laravel 12 应用现在都需要 Carbon 3.x

更新 Laravel 安装器

若使用 Laravel 安装器 CLI 创建新应用,应更新安装器以兼容 Laravel 12.x 与新的 Laravel 起步套件。若当初通过 composer global require 安装,可用 composer global update 更新:

shell
composer global update laravel/installer

若最初通过 php.new 安装 PHP 与 Laravel,可重新运行对应操作系统的 php.new 安装命令,以安装最新版 PHP 与 Laravel 安装器:

shell
/bin/bash -c "$(curl -fsSL https://php.new/install/mac/8.4)"
shell
# Run as administrator...
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://php.new/install/windows/8.4'))
shell
/bin/bash -c "$(curl -fsSL https://php.new/install/linux/8.4)"

或者,若使用的是 Laravel Herd 捆绑的 Laravel 安装器,应将 Herd 更新到最新版本。

认证

更新后的 DatabaseTokenRepository 构造函数签名

影响可能性:极低

Illuminate\Auth\Passwords\DatabaseTokenRepository 类的构造函数现在要求 $expires 参数以秒为单位,而不再是分钟。

并发

并发结果索引映射

影响可能性:低

使用关联数组调用 Concurrency::run 时,并发操作的结果现在会按对应键返回:

php
$result = Concurrency::run([
    'task-1' => fn () => 1 + 1,
    'task-2' => fn () => 2 + 2,
]);

// ['task-1' => 2, 'task-2' => 4]

容器

容器类依赖解析

影响可能性:低

依赖注入容器在解析类实例时,现在会尊重类属性的默认值。若你此前依赖容器在解析时忽略默认值,可能需要据此调整应用:

php
class Example
{
    public function __construct(public ?Carbon $date = null) {}
}

$example = resolve(Example::class);

// <= 11.x
$example->date instanceof Carbon;

// >= 12.x
$example->date === null;

数据库

多 Schema 数据库检查

影响可能性:低

Schema::getTables()Schema::getViews()Schema::getTypes() 方法现在默认包含所有 schema 的结果。可传入 schema 参数以仅获取指定 schema:

php
// All tables on all schemas...
$tables = Schema::getTables();

// All tables on the 'main' schema...
$tables = Schema::getTables(schema: 'main');

// All tables on the 'main' and 'blog' schemas...
$tables = Schema::getTables(schema: ['main', 'blog']);

Schema::getTableListing() 方法现在默认返回带 schema 限定的表名。可传入 schemaQualified 参数按需调整行为:

php
$tables = Schema::getTableListing();
// ['main.migrations', 'main.users', 'blog.posts']

$tables = Schema::getTableListing(schema: 'main');
// ['main.migrations', 'main.users']

$tables = Schema::getTableListing(schema: 'main', schemaQualified: false);
// ['migrations', 'users']

db:tabledb:show 命令现在会在 MySQL、MariaDB 与 SQLite 上输出所有 schema 的结果,行为与 PostgreSQL、SQL Server 一致。

数据库构造函数签名变更

影响可能性:极低

在 Laravel 12 中,若干底层数据库类现在要求通过构造函数提供 Illuminate\Database\Connection 实例。

这些变更主要影响数据库包维护者——极不可能影响普通应用开发。

Illuminate\Database\Schema\Blueprint

Illuminate\Database\Schema\Blueprint 类的构造函数现在要求第一个参数为 Connection 实例。这主要影响手动实例化 Blueprint 的应用或包。

Illuminate\Database\Grammar

Illuminate\Database\Grammar 类的构造函数现在同样需要 Connection 实例。在先前版本中,连接是在构造后通过 setConnection() 方法赋值的。该方法已在 Laravel 12 中移除:

php
// Laravel <= 11.x
$grammar = new MySqlGrammar;
$grammar->setConnection($connection);

// Laravel >= 12.x
$grammar = new MySqlGrammar($connection);

此外,下列 API 已移除或弃用:

  • The Blueprint::getPrefix() method is deprecated.
  • The Connection::withTablePrefix() method has been removed.
  • The Grammar::getTablePrefix() and setTablePrefix() methods are deprecated.
  • The Grammar::setConnection() method has been removed.

处理表前缀时,现在应直接从数据库连接获取:

php
$prefix = $connection->getTablePrefix();

若维护自定义数据库驱动、schema 构建器或 grammar 实现,应检查其构造函数并确保提供了 Connection 实例。

Eloquent

模型与 UUIDv7

影响可能性:中等

HasUuids trait 现在返回兼容 UUID 规范第 7 版的 UUID(有序 UUID)。若希望模型 ID 继续使用有序的 UUIDv4 字符串,应改用 HasVersion4Uuids trait:

php
use Illuminate\Database\Eloquent\Concerns\HasUuids; // [tl! remove]
use Illuminate\Database\Eloquent\Concerns\HasVersion4Uuids as HasUuids; // [tl! add]

HasVersion7Uuids trait 已移除。若此前使用该 trait,应改用现在行为相同的 HasUuids trait。

请求

嵌套数组请求合并

影响可能性:低

$request->mergeIfMissing() 方法现在允许使用「点」语法合并嵌套数组数据。若你此前依赖该方法创建包含「点」语法键名的顶层数组键,可能需要据此调整应用:

php
$request->mergeIfMissing([
    'user.last_name' => 'Otwell',
]);

路由

路由优先级

影响可能性:低

当多个路由同名时,缓存与未缓存路由的匹配行为已统一。也就是说,未缓存路由现在会匹配最先注册的同名路由,而不再是最后注册的那个。

存储

本地文件系统磁盘默认根路径

影响可能性:低

若应用未在文件系统配置中显式定义 local 磁盘,Laravel 现在会将该磁盘的根目录默认为 storage/app/private。先前版本默认为 storage/app。因此,除非另行配置,调用 Storage::disk('local') 将读写 storage/app/private。若要恢复先前行为,可手动定义 local 磁盘并设置所需根路径。

验证

图片验证默认排除 SVG

影响可能性:低

image 验证规则默认不再允许 SVG 图片。若在使用 image 规则时希望允许 SVG,必须显式开启:

php
use Illuminate\Validation\Rules\File;

'photo' => 'required|image:allow_svg'

// Or...
'photo' => ['required', File::image(allowSvg: true)],

其他

我们也建议查看 laravel/laravel GitHub 仓库中的变更。其中许多并非必须,但你可能希望与应用保持同步。本升级指南会涵盖部分变更,另一些(例如配置文件或注释的改动)则不会。你可用 GitHub 对比工具轻松查看差异,并选择对你重要的更新。