升级指南
从 10.x 升级到 11.0
低影响变化
-
Doctrine DBAL 移除
-
Eloquent 模型的 casts 方法
-
空间(Spatial)类型
-
Enumerable 接口
-
UserProvider 接口
-
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 依赖项
-
你需要在应用的
composer.json
文件中更新以下依赖项:"laravel/framework": "^11.0", "nunomaduro/collision": "^8.1", "laravel/breeze": "^2.0", (如果安装) "laravel/cashier": "^15.0", (如果安装) "laravel/dusk": "^8.0", (如果安装) "laravel/jetstream": "^5.0", (如果安装) "laravel/octane": "^2.3", (如果安装) "laravel/passport": "^12.0", (如果安装) "laravel/sanctum": "^4.0", (如果安装) "laravel/scout": "^10.0", (如果安装) "laravel/spark-stripe": "^5.0", (如果安装) "laravel/telescope": "^5.0", (如果安装) "livewire/livewire": "^3.4", (如果安装) "inertiajs/inertia-laravel": "^1.0" (如果安装)
如果你的应用使用了 Laravel Cashier Stripe, Passport, Sanctum, Spark Stripe 或 Telescope,你需要发布它们的迁移文件到应用中。因为从 Laravel 11 起,这些包不再自动加载它们自己的迁移文件。你需要运行以下命令来发布这些迁移:
php artisan vendor:publish --tag=cashier-migrations
php artisan vendor:publish --tag=passport-migrations
php artisan vendor:publish --tag=sanctum-migrations
php artisan vendor:publish --tag=spark-migrations
php artisan vendor:publish --tag=telescope-migrations
此外,您应该查看每个包的升级指南,以确保您了解任何额外的破坏性更改:
如果你手动安装了 Laravel 安装器,应该通过 Composer 更新安装器:
composer global require laravel/installer:^5.6
最后,如果你之前手动添加了 doctrine/dbal
依赖项,可以将其从 composer.json
中移除,因为 Laravel 现在不再依赖此包。
应用结构
Laravel 11 引入了新的默认应用结构,减少了默认文件的数量,特别是服务提供者、中间件和配置文件等。
然而,我们不推荐 Laravel 10 应用在升级到 Laravel 11 后尝试迁移其应用结构,因为 Laravel 11 已经经过调优,可以支持 Laravel 10 的应用结构。
身份验证
密码重新哈希
影响的可能性:低
Laravel 11 将会在身份验证过程中自动重新哈希用户的密码,如果密码的哈希算法的“工作因子”(work factor)自上次哈希以来有所更新。
通常,这不会干扰您的应用程序;但是,如果您的 User 模型的 password 字段名称不同于默认的 password
,您应该通过模型的 authPasswordName
属性指定该字段的名称:
protected $authPasswordName = 'custom_password_field';
或者,您可以通过在应用程序的 config/hashing.php
配置文件中添加 rehash_on_login
选项来禁用密码重新哈希:
'rehash_on_login' => false,
UserProvider 接口
影响的可能性:低
Illuminate\Contracts\Auth\UserProvider
接口新增了一个 rehashPasswordIfRequired
方法。此方法用于在应用的哈希算法工作因子变化时重新哈希并存储用户的密码。
如果您的应用程序或包定义了一个实现此接口的类,您应该在您的实现中添加新的 rehashPasswordIfRequired
方法。可以在 Illuminate\Auth\EloquentUserProvider
类中找到参考实现。
public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false);
Authenticatable 接口
影响的可能性:低
Illuminate\Contracts\Auth\Authenticatable
接口新增了一个 getAuthPasswordName
方法。此方法用于返回你的认证实体的密码字段名称。
如果您的应用程序或包定义了一个实现此接口的类,您应该在您的实现中添加新的 getAuthPasswordName
方法。
public function getAuthPasswordName()
{
return 'password';
}
Laravel 默认的 User 模型会自动接收到这个方法,因为该方法包含在 Illuminate\Auth\Authenticatable
trait 中。
认证异常类(AuthenticationException Class)
影响可能性:非常低
Illuminate\Auth\AuthenticationException
类的 redirectTo
方法现在要求将一个 Illuminate\Http\Request
实例作为第一个参数。如果您手动捕获此异常并调用 redirectTo
方法,您应该相应地更新您的代码:
if ($e instanceof AuthenticationException) {
$path = $e->redirectTo($request);
}
注册时的电子邮件验证通知(Email Verification Notification on Registration)
影响可能性:非常低
如果您的应用程序的 EventServiceProvider
尚未注册 SendEmailVerificationNotification
监听器,则此监听器现在会在 Registered
事件上自动注册。如果您的应用程序的 EventServiceProvider
没有注册该监听器,并且您不希望 Laravel 自动为您注册它,您应该在应用程序的 EventServiceProvider
中定义一个空的 configureEmailVerification
方法:
protected function configureEmailVerification()
{
// ...
}
数据库
Eloquent 模型的 casts
方法
影响可能性:低
基础的 Eloquent 模型类现在定义了一个 casts
方法,以支持属性类型的转换。如果您的应用中的某个模型定义了一个 casts
关系,它可能与现在在基础 Eloquent 模型类中存在的 casts
方法发生冲突。
修改列
影响可能性:高
在修改列时,您现在必须显式包含所有您希望在列定义更改后保留的修改器。任何缺失的属性将会被丢弃。例如,为了保留 unsigned
、default
和 comment
属性,您必须在更改列时显式调用每个修改器,即使这些属性已经由之前的迁移分配给该列。
例如,假设您有一个迁移,创建了一个 votes
列,具有 unsigned
、default
和 comment
属性:
Schema::create('users', function (Blueprint $table) {
$table->integer('votes')->unsigned()->default(1)->comment('The vote count');
});
后来,您编写了一个迁移,将该列更改为可以为 nullable
:
Schema::table('users', function (Blueprint $table) {
$table->integer('votes')->nullable()->change();
});
在 Laravel 10 中,这个迁移将会保留 unsigned
、default
和 comment
属性。然而,在 Laravel 11 中,迁移现在必须显式包括所有先前定义的属性,否则它们将被丢弃:
Schema::table('users', function (Blueprint $table) {
$table->integer('votes')
->unsigned()
->default(1)
->comment('The vote count')
->nullable()
->change();
});
change
方法不会更改列的索引。因此,您可以使用索引修饰符显式添加或删除索引:
// 添加索引...
$table->bigIncrements('id')->primary()->change();
// 删除索引...
$table->char('postal_code', 10)->unique(false)->change();
如果您不想更新应用中所有现有的 "change" 迁移来保留列的现有属性,您可以简单地 压缩您的迁移:
php artisan schema:dump
一旦迁移被压缩,Laravel 会在运行任何待处理迁移之前,使用应用程序的架构文件来 “迁移” 数据库。
浮动点类型
影响的可能性:高
double
和 float
迁移列类型已被重写,以便在所有数据库中保持一致。
double
类型现在创建没有总数字和小数位的标准 SQL DOUBLE
列,因此你可以去除 $total
和 $places
参数:
$table->double('amount');
float
列类型现在会创建一个等效的 FLOAT 列,没有总位数和小数位数的限制,但可以通过可选的 $precision
参数来确定存储大小为 4 字节单精度列或 8 字节双精度列。因此,您可以移除 $total
和 $places
的参数,并根据您的数据库文档,指定可选的 $precision
为所需的值。
// 对于 float('amount', precision: 53),precision: 53 指的是总共可以存储 53 位数字,包括小数点前后的所有位数。
// 换句话说,浮点数的总精度为 53 位数字。
$table->float('amount', precision: 53);
unsignedDecimal
、unsignedDouble
和 unsignedFloat
方法已被移除,因为 MySQL 已弃用这些列类型的 unsigned
修饰符,而且其它数据库系统从未对此进行标准化。然而,如果您希望继续使用这些列类型的弃用 unsigned
属性,可以将 unsigned
方法链式调用到列定义中:
$table->decimal('amount', total: 8, places: 2)->unsigned();
$table->double('amount')->unsigned();
$table->float('amount', precision: 53)->unsigned();
专用 MariaDB 驱动
影响可能性:非常低
Laravel 11 为 MariaDB 数据库提供了一个专用的数据库驱动,而不再总是使用 MySQL 驱动。
如果您的应用程序连接到 MariaDB 数据库,您可以更新连接配置为新的 mariadb
驱动,以便未来能够利用 MariaDB 特定的功能:
'driver' => 'mariadb',
'url' => env('DB_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
// ...
当前,新的 MariaDB 驱动行为与现有的 MySQL 驱动相同,唯一的区别是,uuid
schema 构建方法会创建原生 UUID 列,而不是 char(36)
列。
如果您的现有迁移使用了 uuid
schema 构建方法,并且您选择使用新的 mariadb
数据库驱动,则应更新迁移中的 uuid
方法调用为 char
类型,以避免破坏性更改或意外行为:
Schema::table('users', function (Blueprint $table) {
$table->char('uuid', 36);
// ...
});
空间类型
影响可能性:低
数据库迁移中的空间(spatial)列类型已经重新编写,以在所有数据库中保持一致。因此,您可以从迁移中移除 point
、lineString
、polygon
、geometryCollection
、multiPoint
、multiLineString
、multiPolygon
和 multiPolygonZ
方法,并改用 geometry
或 geography
方法:
$table->geometry('shapes');
$table->geography('coordinates');
如果您希望在 MySQL、MariaDB 和 PostgreSQL 中显式限制列存储的值类型或空间参考系统标识符(SRID),可以将 subtype
和 srid
参数传递给方法:
$table->geometry('dimension', subtype: 'polygon', srid: 0);
$table->geography('latitude', subtype: 'point', srid: 4326);
相应地,PostgreSQL 语法中的 isGeometry
和 projection
列修饰符已被移除。
Doctrine DBAL 移除
影响可能性:低
以下与 Doctrine DBAL 相关的类和方法已被移除。Laravel 不再依赖该包,且不再需要注册自定义 Doctrine 类型来正确创建和修改各种列类型,这些列类型以前需要自定义类型:
-
Illuminate\Database\Schema\Builder::$alwaysUsesNativeSchemaOperationsIfPossible
类属性 -
Illuminate\Database\Schema\Builder::useNativeSchemaOperationsIfPossible()
方法 -
Illuminate\Database\Connection::usingNativeSchemaOperations()
方法 -
Illuminate\Database\Connection::isDoctrineAvailable()
方法 -
Illuminate\Database\Connection::getDoctrineConnection()
方法 -
Illuminate\Database\Connection::getDoctrineSchemaManager()
方法 -
Illuminate\Database\Connection::getDoctrineColumn()
方法 -
Illuminate\Database\Connection::registerDoctrineType()
方法 -
Illuminate\Database\DatabaseManager::registerDoctrineType()
方法 -
Illuminate\Database\PDO
目录 -
Illuminate\Database\DBAL\TimestampType
类 -
Illuminate\Database\Schema\Grammars\ChangeColumn
类 -
Illuminate\Database\Schema\Grammars\RenameColumn
类 -
Illuminate\Database\Schema\Grammars\Grammar::getDoctrineTableDiff()
方法
此外,通过在应用程序的数据库配置文件中使用 dbal.types
来注册自定义 Doctrine 类型也不再需要。
如果您之前使用 Doctrine DBAL 来检查数据库及其相关表,您现在可以使用 Laravel 的新的原生 schema 方法(如 Schema::getTables()
、Schema::getColumns()
、Schema::getIndexes()
、Schema::getForeignKeys()
等)来代替。
弃用的模式(Schema)方法
影响可能性:非常低
已移除基于 Doctrine 的 Schema::getAllTables()
、Schema::getAllViews()
和 Schema::getAllTypes()
方法,取而代之的是新的 Laravel 原生方法:Schema::getTables()
、Schema::getViews()
和 Schema::getTypes()
方法。
在使用 PostgreSQL 和 SQL Server 时,新的模式方法不再接受三部分引用(例如 database.schema.table
)。因此,您应该使用 connection()
来声明数据库,如下所示:
Schema::connection('database')->hasTable('schema.table');
Packages
将服务提供者发布到应用程序
影响可能性:非常低
如果您编写了一个 Laravel 包,手动将服务提供者发布到应用程序的 app/Providers
目录,并手动修改应用程序的 config/app.php
配置文件来注册服务提供者,您应该更新您的包以使用新的 ServiceProvider::addProviderToBootstrapFile
方法。
addProviderToBootstrapFile
方法将自动把您发布的服务提供者添加到应用程序的 bootstrap/providers.php
文件中,因为在新的 Laravel 11 应用程序中,config/app.php
配置文件中不再存在 providers
数组。
use Illuminate\Support\ServiceProvider;
ServiceProvider::addProviderToBootstrapFile(Provider::class);
队列
速率限制
每秒限流
影响的可能性:中
Laravel 11 支持每秒速率限制,而不仅限于每分钟的粒度。对于这个变化,您需要注意以下一些潜在的破坏性更改。
GlobalLimit 类构造函数 现在接受秒数而不是分钟数。此类没有文档,通常不会被您的应用程序使用:
new GlobalLimit($attempts, 2 * 60);
Limit 类构造函数 现在接受秒数而不是分钟数。该类的所有文档化用法都限于静态构造函数,如 Limit::perMinute
和 Limit::perSecond
。然而,如果您手动实例化此类,您应该更新您的应用程序,向类构造函数提供秒数:
new Limit($key, $attempts, 2 * 60);
Limit 类的 decayMinutes 属性 已更名为 decaySeconds
,并且现在包含秒数而不是分钟数。
Illuminate\Queue\Middleware\ThrottlesExceptions 和 Illuminate\Queue\Middleware\ThrottlesExceptionsWithRedis 类的构造函数现在接受秒数而不是分钟数:
new ThrottlesExceptions($attempts, 2 * 60);
new ThrottlesExceptionsWithRedis($attempts, 2 * 60);
Cashier Stripe
Cashier Stripe 更新
影响可能性:高
Laravel 11 不再支持 Cashier Stripe 14.x。因此,您应该在 composer.json 文件中将应用程序的 Laravel Cashier Stripe 依赖更新为 ^15.0。
Cashier Stripe 15.0 不再自动加载来自其自身迁移目录的迁移文件。相反,您需要运行以下命令将 Cashier Stripe 的迁移文件发布到您的应用程序中:
php artisan vendor:publish --tag=cashier-migrations
请查看完整的 Cashier Stripe 升级指南 以了解更多破坏性更改。
Spark(Stripe)
更新 Spark Stripe
影响可能性:高
Laravel 11 不再支持 Laravel Spark Stripe 4.x。因此,您需要将应用程序中的 Laravel Spark Stripe 依赖项更新为 ^5.0,在 composer.json
文件中进行更改。
Spark Stripe 5.0 不再自动加载来自其自身迁移目录的迁移文件。相反,您需要运行以下命令,将 Spark Stripe 的迁移文件发布到您的应用程序:
php artisan vendor:publish --tag=spark-migrations
请查阅完整的 Spark Stripe 升级指南,以了解更多破坏性更改。
Passport
更新 Passport
影响可能性:高
Laravel 11 不再支持 Laravel Passport 11.x。因此,您需要将应用程序中的 Laravel Passport 依赖项更新为 ^12.0,在 composer.json
文件中进行更改。
Passport 12.0 不再自动加载来自其自身迁移目录的迁移文件。相反,您需要运行以下命令,将 Passport 的迁移文件发布到您的应用程序:
php artisan vendor:publish --tag=passport-migrations
此外,密码授权类型(password grant)默认被禁用。如果需要启用它,可以在应用程序的 AppServiceProvider
的 boot
方法中调用 enablePasswordGrant
方法:
public function boot(): void
{
Passport::enablePasswordGrant();
}
Sanctum
更新 Sanctum
影响可能性:高
Laravel 11 不再支持 Laravel Sanctum 3.x。因此,您需要将应用程序中的 Laravel Sanctum 依赖项更新为 ^4.0,在 composer.json
文件中进行更改。
Sanctum 4.0 不再自动加载来自其自身迁移目录的迁移文件。相反,您需要运行以下命令,将 Sanctum 的迁移文件发布到您的应用程序:
php artisan vendor:publish --tag=sanctum-migrations
接下来,在应用程序的 config/sanctum.php
配置文件中,您需要将对 authenticate_session
、encrypt_cookies
和 validate_csrf_token
中间件的引用更新为以下内容:
'middleware' => [
'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class,
'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class,
'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class,
],
Spatie Once Package
影响可能性:中
Laravel 11 现在提供了自己的 once
函数,确保给定的闭包只执行一次。因此,如果您的应用程序依赖于 spatie/once
包,您应将其从应用程序的 composer.json
文件中移除,以避免冲突。
Miscellaneous
我们还鼓励您查看 laravel/laravel
GitHub 仓库 中的更改。虽然这些更改并非必需,但您可能希望将这些文件与应用程序保持同步。部分更改将在本升级指南中提及,但其它更改,如配置文件或注释的更改,则不会。您可以轻松使用 GitHub 比较工具 查看这些更改,并选择对您重要的更新。