升级指南
高影响变更
中等影响变更
低影响变更
从 11.x 升级到 12.0
预计升级时间:5 分钟
INFO
我们尽量记录每一处可能的破坏性变更。由于部分变更位于框架较冷门的区域,其中只有一部分可能真正影响你的应用。想节省时间?可使用 Laravel Shift 协助自动化升级。
更新依赖
影响可能性:高
应在应用的 composer.json 中更新下列依赖:
laravel/frameworkto^12.0phpunit/phpunitto^11.0pestphp/pestto^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 更新:
composer global update laravel/installer若最初通过 php.new 安装 PHP 与 Laravel,可重新运行对应操作系统的 php.new 安装命令,以安装最新版 PHP 与 Laravel 安装器:
/bin/bash -c "$(curl -fsSL https://php.new/install/mac/8.4)"# 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'))/bin/bash -c "$(curl -fsSL https://php.new/install/linux/8.4)"或者,若使用的是 Laravel Herd 捆绑的 Laravel 安装器,应将 Herd 更新到最新版本。
认证
更新后的 DatabaseTokenRepository 构造函数签名
影响可能性:极低
Illuminate\Auth\Passwords\DatabaseTokenRepository 类的构造函数现在要求 $expires 参数以秒为单位,而不再是分钟。
并发
并发结果索引映射
影响可能性:低
使用关联数组调用 Concurrency::run 时,并发操作的结果现在会按对应键返回:
$result = Concurrency::run([
'task-1' => fn () => 1 + 1,
'task-2' => fn () => 2 + 2,
]);
// ['task-1' => 2, 'task-2' => 4]容器
容器类依赖解析
影响可能性:低
依赖注入容器在解析类实例时,现在会尊重类属性的默认值。若你此前依赖容器在解析时忽略默认值,可能需要据此调整应用:
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:
// 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 参数按需调整行为:
$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:table 与 db: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 中移除:
// 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()andsetTablePrefix()methods are deprecated. - The
Grammar::setConnection()method has been removed.
处理表前缀时,现在应直接从数据库连接获取:
$prefix = $connection->getTablePrefix();若维护自定义数据库驱动、schema 构建器或 grammar 实现,应检查其构造函数并确保提供了 Connection 实例。
Eloquent
模型与 UUIDv7
影响可能性:中等
HasUuids trait 现在返回兼容 UUID 规范第 7 版的 UUID(有序 UUID)。若希望模型 ID 继续使用有序的 UUIDv4 字符串,应改用 HasVersion4Uuids trait:
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() 方法现在允许使用「点」语法合并嵌套数组数据。若你此前依赖该方法创建包含「点」语法键名的顶层数组键,可能需要据此调整应用:
$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,必须显式开启:
use Illuminate\Validation\Rules\File;
'photo' => 'required|image:allow_svg'
// Or...
'photo' => ['required', File::image(allowSvg: true)],其他
我们也建议查看 laravel/laravel GitHub 仓库中的变更。其中许多并非必须,但你可能希望与应用保持同步。本升级指南会涵盖部分变更,另一些(例如配置文件或注释的改动)则不会。你可用 GitHub 对比工具轻松查看差异,并选择对你重要的更新。