升级指南

从 10.x 升级到 11.0

高影响变化

更新依赖
应用结构
浮点数类型
修改列
SQLite 最低版本
升级 Sanctum

中等影响变化

Carbon 3
密码再处理
每秒请求限流

较小影响变化

Doctrine DBAL 移除
Eloquent 模型 php casts 方法
空间类型
Spatie Once 包
php Enumerable 契约
php UserProvider 契约
php Authenticatable 契约

从 10.x 升级到 11.0

预计升级时间:15 分钟
[!注意]
我们试图记录每一个可能的破坏性变更。由于其中一些破坏性变更位于框架的底层部分,因此只有其中一部分变更实际上会影响你的应用程序。想节省时间吗?你可以使用 Laravel Shift 来帮助自动升级你的应用程序。

更新依赖项

影响可能性:高

要求PHP 8.2.0
Laravel 当前要求 PHP 8.2.0 或更高版本。

要求curl 7.34.0
Laravel 的 HTTP 客户端要求 curl 7.34.0 或更高版本。

Composer 依赖项
你应该在应用程序的 php composer.json 文件中更新以下依赖项:

php laravel/framework 更新到 php ^11.0
php nunomaduro/collision 更新到 php ^8.1
php laravel/breeze 更新到 php ^2.0 (若安装此依赖)
php laravel/cashier 更新到 php ^15.0 (若安装此依赖)
php laravel/dusk 更新到 php ^8.0 (若安装此依赖)
php laravel/jetstream 更新到 php ^5.0 (若安装此依赖)
php laravel/octane 更新到 php ^2.3 (若安装此依赖)
php laravel/passport 更新到 php ^12.0 (若安装此依赖)
php laravel/sanctum 更新到 php ^4.0 (若安装此依赖)
php laravel/scout 更新到 php ^10.0 (若安装此依赖)
php laravel/spark-stripe 更新到 php ^5.0 (若安装此依赖)
php laravel/telescope 更新到 php ^5.0 (若安装此依赖)
php inertiajs/inertia-laravel 更新到 php ^1.0 (若安装此依赖)
如果你的应用程序使用了 Laravel Cashier Stripe、Passport、Sanctum、Spark Stripe 或 Telescope,你需要将它们的迁移文件发布到你的应用程序中。Cashier Stripe、Passport、Sanctum、Spark Stripe 和 Telescope 不再自动从它们自己的迁移目录加载迁移文件。因此,你应该运行以下命令将它们的迁移文件发布到你的应用程序:

  1. php artisan vendor:publish --tag=cashier-migrations
  2. php artisan vendor:publish --tag=passport-migrations
  3. php artisan vendor:publish --tag=sanctum-migrations
  4. php artisan vendor:publish --tag=spark-migrations
  5. php artisan vendor:publish --tag=telescope-migrations

此外,你应该查看这些包的升级指南,以确保你了解任何其他的重大变更:

Laravel Cashier Stripe
Laravel Passport
Laravel Sanctum
Laravel Spark Stripe
Laravel Telescope
如果你已手动安装了 Laravel 安装器,你应该通过 Composer 更新安装器:

  1. composer global require laravel/installer:^5.6

最后,如果你之前已将 php doctrine/dbal Composer 依赖项添加到你的应用程序,你可以将其移除,因为 Laravel 不再依赖这个包。

应用程序结构

Laravel 11 引入了一种新的默认应用程序结构,包含更少的默认文件。具体来说,新的 Laravel 应用程序包含更少的服务提供者、中间件和配置文件。

然而,我们不推荐从 Laravel 10 升级到 Laravel 11 的应用程序尝试迁移它们的应用程序结构,因为 Laravel 11 已经精心调整以支持 Laravel 10 的应用程序结构。

认证

密码重哈希
如果自密码最后一次哈希以来你的哈希算法的“工作因子”已更新,Laravel 11 将在认证过程中自动重新哈希你用户的密码。

通常情况下,这不应该影响你的应用程序;然而,你可以通过在应用程序的 php config/hashing.php 配置文件中添加 php rehash_on_login 选项来禁用此行为:

  1. 'rehash_on_login' => false,

php UserProvider 合约
影响可能性:低

php Illuminate\Contracts\Auth\UserProvider 合约新增了一个 php rehashPasswordIfRequired 方法。该方法负责在应用程序的哈希算法工作因子发生变化时,重新哈希并存储用户的密码。

如果你的应用程序或包定义了一个实现此接口的类,你应该在你的实现中添加新的 php rehashPasswordIfRequired 方法。你可以在 php Illuminate\Auth\EloquentUserProvider 类中找到一个参考实现:

  1. public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false);

php Authenticatable 合约
影响可能性:低

php Illuminate\Contracts\Auth\Authenticatable 合约新增了一个 php getAuthPasswordName 方法。该方法负责返回你的认证实体的密码列的名称。

如果你的应用程序或包定义了一个实现此接口的类,你应该在你的实现中添加新的 php getAuthPasswordName 方法:

  1. public function getAuthPasswordName()
  2. {
  3. return 'password';
  4. }

Laravel 自带的默认 php User 模型自动获得此方法,因为该方法包含在 php Illuminate\Auth\Authenticatable 特性中。

php AuthenticationException
影响可能性:非常低

php Illuminate\Auth\AuthenticationException 类的 php redirectTo 方法现在要求其第一个参数为 php Illuminate\Http\Request 实例。如果你在手动捕获此异常并调用 php redirectTo 方法,你应该相应地更新你的代码:

  1. if ($e instanceof AuthenticationException) {
  2. $path = $e->redirectTo($request);
  3. }

缓存

缓存键前缀
影响可能性:非常低

以前,如果为 DynamoDB、Memcached 或 Redis 缓存存储定义了缓存键前缀,Laravel 会在前缀后添加一个 php :。在 Laravel 11 中,缓存键前缀不再添加 php : 后缀。如果你想保持之前的前缀行为,你可以手动在你的缓存键前缀中添加 php : 后缀。

集合

php Enumerable 合约
影响可能性:低

php Illuminate\Support\Enumerable 合约的 php dump 方法已更新,以接受一个可变参数 php ...$args。如果你正在实现这个接口,你应该相应地更新你的实现:

  1. public function dump(...$args);

数据库

SQLite 3.35.0+
影响可能性:高

如果你的应用程序正在使用 SQLite 数据库,需要 SQLite 3.35.0 或更高版本。

Eloquent 模型 php casts 方法
影响可能性:低

基础 Eloquent 模型类现在定义了一个 php casts 方法,以支持属性转换的定义。如果你的应用程序中的某个模型正在定义一个 php casts 关系,它可能与现在基础 Eloquent 模型类上存在的 php casts 方法冲突。

修改列
影响可能性:高

在修改列时,你现在必须明确包括你想在列定义更改后保留的所有修饰符。任何缺失的属性都将被丢弃。例如,要保留 php unsignedphp defaultphp comment 属性,即使这些属性已由之前的迁移分配给该列,你也必须在更改列时显式调用每个修饰符。

例如,假设你有一个迁移,它创建了一个带有 php unsignedphp defaultphp comment 属性的 php votes 列:

  1. Schema::create('users', function (Blueprint $table) {
  2. $table->integer('votes')->unsigned()->default(1)->comment('投票数');
  3. });

后来,你编写了一个迁移,将该列更改为同时可为空:

  1. Schema::table('users', function (Blueprint $table) {
  2. $table->integer('votes')->nullable()->change();
  3. });

在 Laravel 10 中,这个迁移将保留列上的 php unsignedphp defaultphp comment 属性。然而,在 Laravel 11 中,迁移现在必须也包括之前在列上定义的所有属性。否则,这些属性将被丢弃:

  1. Schema::table('users', function (Blueprint $table) {
  2. $table->integer('votes')
  3. ->unsigned()
  4. ->default(1)
  5. ->comment('投票数')
  6. ->nullable()
  7. ->change();
  8. });

php change 方法不会改变列的索引。因此,你可以使用索引修饰符在修改列时显式添加或删除索引:

  1. // 添加索引...
  2. $table->bigIncrements('id')->primary()->change();
  3. // 删除索引...
  4. $table->char('postal_code', 10)->unique(false)->change();

如果你不想更新应用程序中所有现有的“change”迁移以保留列的现有属性,你可以简单地压缩你的迁移:

  1. php artisan schema:dump

一旦你的迁移被压缩,Laravel 将使用你的应用程序的架构文件“迁移”数据库,然后运行任何待处理的迁移。

浮点类型
影响可能性:高

php doublephp float 迁移列类型已被重写,以确保在所有数据库中的一致性。

php double 列类型现在创建一个不带总位数和小数位(小数点后的数字)的 php DOUBLE 等效列,这是标准的 SQL 语法。因此,你可以移除 php $totalphp $places 参数:

  1. $table->double('amount');

php float 列类型现在创建一个不带总位数和小数位(小数点后的数字)的 php FLOAT 等效列,但可以选择性地指定 php $precision 来决定存储大小,作为一个 4 字节的单精度列或一个 8 字节的双精度列。因此,你可以移除 php $totalphp $places 参数,并根据你的数据库文档指定你希望的 php $precision 值:

  1. $table->float('amount', precision: 53);

php unsignedDecimalphp unsignedDoublephp unsignedFloat 方法已被移除,因为这些列类型的无符号修饰符已被 MySQL 弃用,并且从未在其他数据库系统中标准化。然而,如果你希望继续使用这些列类型的已弃用无符号属性,你可以将 php unsigned 方法链接到列的定义上:

  1. $table->decimal('amount', total: 8, places: 2)->unsigned();
  2. $table->double('amount')->unsigned();
  3. $table->float('amount', precision: 53)->unsigned();

专用 MariaDB 驱动
影响可能性:非常低

Laravel 11 不再总是在连接到 MariaDB 数据库时使用 MySQL 驱动,而是添加了一个专用的 MariaDB 数据库驱动。

如果你的应用程序连接到 MariaDB 数据库,你可以更新连接配置为新的 php mariadb 驱动,以便在将来从 MariaDB 的特定功能中获益:

  1. 'driver' => 'mariadb',
  2. 'url' => env('DB_URL'),
  3. 'host' => env('DB_HOST', '127.0.0.1'),
  4. 'port' => env('DB_PORT', '3306'),
  5. // ...

目前,新的 MariaDB 驱动的行为与当前的 MySQL 驱动类似,但有一个例外:php uuid 架构构建方法会创建原生 UUID 列而不是 php char(36) 列。

如果你现有的迁移使用了 php uuid 架构构建方法,并且你选择使用新的 php mariadb 数据库驱动,你应该将迁移中调用 php uuid 方法的地方更新为 php char,以避免破坏性更改或意外行为:

  1. Schema::table('users', function (Blueprint $table) {
  2. $table->char('uuid', 36);
  3. // ...
  4. });

空间类型
影响可能性:低

数据库迁移的空间列类型已被重写,以确保在所有数据库中的一致性。因此,你可以从你的迁移中移除 php pointphp lineStringphp polygonphp geometryCollectionphp multiPointphp multiLineStringphp multiPolygonphp multiPolygonZ 方法,改用 php geometryphp geography 方法:

  1. $table->geometry('shapes');
  2. $table->geography('coordinates');

为了在 MySQL、MariaDB 和 PostgreSQL 上明确限制存储在列中的值的类型或空间参考系统标识符,你可以将 php subtypephp srid 传递给方法:

  1. $table->geometry('dimension', subtype: 'polygon', srid: 0);
  2. $table->geography('latitude', subtype: 'point', srid: 4326);

PostgreSQL 语法的 php isGeometryphp projection 列修饰符已相应地被移除。

Doctrine DBAL 移除
影响可能性:低

以下列出的 Doctrine DBAL 相关类和方法已被移除。Laravel 不再依赖此包,且注册自定义 Doctrine 类型对于正确创建和修改之前需要自定义类型的各种列类型不再必要:

php Illuminate\Database\Schema\Builder::$alwaysUsesNativeSchemaOperationsIfPossible 类属性
php Illuminate\Database\Schema\Builder::useNativeSchemaOperationsIfPossible() 方法
php Illuminate\Database\Connection::usingNativeSchemaOperations() 方法
php Illuminate\Database\Connection::isDoctrineAvailable() 方法
php Illuminate\Database\Connection::getDoctrineConnection() 方法
php Illuminate\Database\Connection::getDoctrineSchemaManager() 方法
php Illuminate\Database\Connection::getDoctrineColumn() 方法
php Illuminate\Database\Connection::registerDoctrineType() 方法
php Illuminate\Database\DatabaseManager::registerDoctrineType() 方法
php Illuminate\Database\PDO 目录
php Illuminate\Database\DBAL\TimestampType
php Illuminate\Database\Schema\Grammars\ChangeColumn
php Illuminate\Database\Schema\Grammars\RenameColumn
php Illuminate\Database\Schema\Grammars\Grammar::getDoctrineTableDiff() 方法
此外,通过应用程序的 php database 配置文件中的 php dbal.types 注册自定义 Doctrine 类型已不再需要。

如果你之前使用 Doctrine DBAL 来检查你的数据库及其关联表,你可以改用 Laravel 的新的原生架构方法(php Schema::getTables()php Schema::getColumns()php Schema::getIndexes()php Schema::getForeignKeys() 等)。

已废弃的架构方法
影响可能性:非常低

基于 Doctrine 的已废弃方法 php Schema::getAllTables()php Schema::getAllViews()php Schema::getAllTypes() 已被移除,取而代之的是新的 Laravel 原生方法 php Schema::getTables()php Schema::getViews()php Schema::getTypes()

在使用 PostgreSQL 和 SQL Server 时,新的架构方法不会接受三部分引用(例如 php database.schema.table)。因此,你应该使用 php connection() 来声明数据库:

  1. Schema::connection('database')->hasTable('schema.table');

架构构建器 php getColumnType() 方法
影响可能性:非常低

php Schema::getColumnType() 方法现在始终返回给定列的实际类型,而不是 Doctrine DBAL 等效类型。

数据库连接接口
影响可能性:非常低

php Illuminate\Database\ConnectionInterface 接口新增了一个 php scalar 方法。如果你正在定义自己的该接口实现,你应该在你的实现中添加 php scalar 方法:

  1. public function scalar($query, $bindings = [], $useReadPdo = true);

日期

Carbon 3
影响可能性:中等

Laravel 11 支持 Carbon 2 和 Carbon 3。Carbon 是一个广泛用于 Laravel 及其生态系统中的包的日期操作库。如果你升级到 Carbon 3,请注意 php diffIn* 方法现在返回浮点数,并且可能返回负值以指示时间方向,这与 Carbon 2 的行为有显著不同。查看 Carbon 的 变更日志以获取如何处理这些及其他变更的详细信息。

邮件

php Mailer 合约
影响可能性:非常低

php Illuminate\Contracts\Mail\Mailer 合约新增了一个 php sendNow 方法。如果你的应用程序或包手动实现了这个合约,你应该在你的实现中添加新的 php sendNow 方法:

  1. public function sendNow($mailable, array $data = [], $callback = null);

将服务提供者发布到应用程序
影响可能性:非常低

如果你编写了一个 Laravel 包,该包手动将服务提供者发布到应用程序的 php app/Providers 目录,并手动修改应用程序的 php config/app.php 配置文件来注册服务提供者,你应该更新你的包以使用新的 php ServiceProvider::addProviderToBootstrapFile 方法。

php addProviderToBootstrapFile 方法将自动将你发布的服务提供者添加到应用程序的 php bootstrap/providers.php 文件中,因为在新的 Laravel 11 应用程序中 php config/app.php 配置文件内不存在 php providers 数组。

  1. use Illuminate\Support\ServiceProvider;
  2. ServiceProvider::addProviderToBootstrapFile(Provider::class);

队列

php BatchRepository 接口
影响可能性:非常低

php Illuminate\Bus\BatchRepository 接口新增了一个 php rollBack 方法。如果你在自己的包或应用程序中实现了这个接口,你应该在你的实现中添加这个方法:

  1. public function rollBack();

数据库事务中的同步作业
影响可能性:非常低

以前,同步作业(使用 php sync 队列驱动的作业)会立即执行,无论队列连接的 php after_commit 配置选项是否设置为 php true 或是否调用了作业上的 php afterCommit 方法。

在 Laravel 11 中,同步队列作业现在将遵守队列连接或作业的“提交后”配置。

速率限制

每秒速率限制
影响可能性:中等

Laravel 11 支持每秒速率限制,而不再局限于每分钟的粒度。与此变更相关,有多种可能的破坏性更改你应当了解。

php GlobalLimit 类的构造函数现在接受秒而不是分钟。这个类没有文档记录,通常不会被你的应用程序使用:

  1. new GlobalLimit($attempts, 2 * 60);

php Limit 类的构造函数现在接受秒而不是分钟。所有文档记录的此类用法都限于静态构造函数,如 php Limit::perMinutephp Limit::perSecond。然而,如果你手动实例化这个类,你应该更新你的应用程序,以提供秒数给类的构造函数:

  1. new Limit($key, $attempts, 2 * 60);

php Limit 类的 php decayMinutes 属性已更名为 php decaySeconds,现在包含秒而不是分钟。

php Illuminate\Queue\Middleware\ThrottlesExceptionsphp Illuminate\Queue\Middleware\ThrottlesExceptionsWithRedis 类的构造函数现在接受秒而不是分钟:

  1. new ThrottlesExceptions($attempts, 2 * 60);
  2. new ThrottlesExceptionsWithRedis($attempts, 2 * 60);

Cashier Stripe

更新 Cashier Stripe
影响可能性:高

Laravel 11 不再支持 Cashier Stripe 14.x。因此,你应该在你的 php composer.json 文件中更新你的应用程序的 Laravel Cashier Stripe 依赖到 php ^15.0

Cashier Stripe 15.0 不再自动从其自己的迁移目录加载迁移。相反,你应该运行以下命令将 Cashier Stripe 的迁移发布到你的应用程序:

  1. php artisan vendor:publish --tag=cashier-migrations

请查阅完整的 Cashier Stripe 升级指南 以了解更多破坏性变更。

Spark (Stripe)

更新 Spark Stripe
影响可能性:高

Laravel 11 不再支持 Laravel Spark Stripe 4.x。因此,你应该在你的 php composer.json 文件中更新你的应用程序的 Laravel Spark Stripe 依赖到 php ^5.0

Spark Stripe 5.0 不再自动从其自己的迁移目录加载迁移。相反,你应该运行以下命令将 Spark Stripe 的迁移发布到你的应用程序:

  1. php artisan vendor:publish --tag=spark-migrations

请查阅完整的 Spark Stripe 升级指南 以了解更多破坏性变更。

Passport

更新 Passport
影响可能性:高

Laravel 11 不再支持 Laravel Passport 11.x。因此,你应该在你的 php composer.json 文件中更新你的应用程序的 Laravel Passport 依赖到 php ^12.0

Passport 12.0 不再自动从其自己的迁移目录加载迁移。相反,你应该运行以下命令将 Passport 的迁移发布到你的应用程序:

  1. php artisan vendor:publish --tag=passport-migrations

此外,默认情况下禁用了密码授权类型。你可以通过在你的应用程序的 php AppServiceProviderphp boot 方法中调用 php enablePasswordGrant 方法来启用它:

  1. public function boot(): void
  2. {
  3. Passport::enablePasswordGrant();
  4. }

Sanctum

更新 Sanctum
影响可能性:高

Laravel 11 不再支持 Laravel Sanctum 3.x。因此,你应该在你的 php composer.json 文件中更新你的应用程序的 Laravel Sanctum 依赖到 php ^4.0

Sanctum 4.0 不再自动从其自己的迁移目录加载迁移。相反,你应该运行以下命令将 Sanctum 的迁移发布到你的应用程序:

  1. php artisan vendor:publish --tag=sanctum-migrations

然后,在你的应用程序的 php config/sanctum.php 配置文件中,你应该将 php authenticate_sessionphp encrypt_cookiesphp validate_csrf_token 中间件的引用更新为以下内容:

  1. 'middleware' => [
  2. 'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class,
  3. 'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class,
  4. 'validate_csfr_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class,
  5. ],

Telescope

更新 Telescope
影响可能性:高

Laravel 11 不再支持 Laravel Telescope 4.x。因此,你应该在你的 php composer.json 文件中更新你的应用程序的 Laravel Telescope 依赖到 php ^5.0

Telescope 5.0 不再自动从其自己的迁移目录加载迁移。相反,你应该运行以下命令将 Telescope 的迁移发布到你的应用程序:

  1. php artisan vendor:publish --tag=telescope-migrations

Spatie Once 包

影响可能性:中等

Laravel 11 现在提供了自己的 php once 函数,以确保给定的闭包只执行一次。因此,如果你的应用程序依赖于 php spatie/once 包,你应该从你的应用程序的 php composer.json 文件中移除它,以避免冲突。

其他

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