Laravel 11 升级指南

刚刚翻译了一下升级指南,分享给大家。更多译文可移步此处

高影响更新

  • 更新依赖
  • 应用结构
  • 浮点型类型
  • 修改数据库字段
  • SQLite 最低版本
  • 更新 Sanctum

中等影响更新

  • Carbon 3
  • 密码重新哈希
  • 按秒限流

低影响更新

  • 移除 Doctrine DBAL
  • Eloquent 模型的 casts 方法
  • Spatial 类型
  • Spatie Once 包
  • Enumerable Contract
  • UserProvider Contract
  • Authenticatable Contract

从 10.x 升级到 11.0

预计升级时间:15分钟

我们试图每一个可能的破坏性更新记入文档。由于这些破坏性更新中有一些位于框架的模糊部分,因此只有其中的一部分更改可能会实际影响你的应用。想节省时间吗?您可以使用 Laravel Shift 来帮助实现应用升级的自动化。

更新依赖

影响可能性:高

要求 PHP 8.2.0

Laravel 现在要求 PHP 8.2.0 及以上版本。

Composer 依赖

你应该再应用的composer.json 文件中更新以下依赖

  • laravel/framework to ^11.0
  • nunomaduro/collision to ^8.1
  • laravel/cashier-stripe to ^15.0 (如果安装了)
  • laravel/passport to ^12.0 (如果安装了)
  • laravel/sanctum to ^4.0 (如果安装了)
  • laravel/spark-stripe to ^5.0 (如果安装了)
  • laravel/telescope to ^5.0 (如果安装了)

如果您的应用程序使用的是 Laravel Cashier Stripe、Passport、Sanctum、Spark Stripe 或 Telescope,则需要将它们的迁移发布到应用中。Cash Stripe、Passport、Sanctum、Spark Stripe 和 Telescope 不再自动从它们自己的迁移目录加载迁移。因此,你应该运行以下命令将迁移发布到你的应用中:

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 installer,你应该通过 Composer 更新 installer:

composer global require laravel/installer:^5.6

最后,如果你之前已将 doctrine/dbal 依赖项添加到应用程序中,则可以删除它,因为 Laravel 不再依赖于此包。

应用结构

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

然而,我们不建议升级到 Laravel 11 的 Laravel 10 应用尝试迁移其应用结构,因为 Laravel 已经经过精心调整,也支持 Laravel 10 的应用结构。

身份验证

密码重新哈希

如果您的哈希算法的“工作因子”自上次哈希密码以来已经更新,Laravel 11 将在身份验证期间自动重新哈希用户的密码。

通常情况下,这不会破坏你的应用;但是,你可以通过将 rehash_on_login 选项添加到应用的 config/hashing.php 配置文件中来禁用此行为:

'rehash_on_login' => false,

UserProvider Contract

影响可能性:低

Illuminate\Contracts\Auth\UserProvider contract 接受一个新的 rehashPasswordIfRequired 方法。当应用程序的哈希算法工作因子发生变化时,此方法负责重新哈希并将用户密码存到在 storage 中。

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

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

Authenticatable Contract

影响可能性:低

Illuminate\Contracts\Auth\Authenticatable contract 已接收到新的 getAuthPasswordName 方法。此方法负责返回可认证实体的密码列的名称。

如果你的应用或包定义了实现此接口的类,则应将新的 getAuthPasswordName 方法添加到实现中:

public function getAuthPasswordName()
{
    return 'password';
}

Laravel 中包含的默认 User 模型会自动接收此方法,因为该方法包含在 Illuminate\Auth\Authenticatable trait 中。

缓存

缓存密钥前缀

影响可能性:低

以前,如果为 DynamoDB、Memcached 或 Redis 缓存存储定义了缓存密钥前缀,Laravel 会在前缀后附加一个 :。在 Laravel 11 中,缓存密钥前缀不接收 : 后缀。如果您想保持以前的前缀行为,可以手动将 : 后缀添加到缓存密钥前缀中。

集合

Enumerable Contract

影响可能性:低

Illuminate\Support\Enumerable Contract的转储方法已更新为接受可变 ...$args 参数。如果你实现了此接口,则应相应地更新你的实现:

public function dump(...$args);

数据库

SQLite 3.35.0+

影响可能性:高

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

Eloquent 模型 casts 方法

影响可能性:低

基础的 Eloquent 模型类现在定义了一个 casts 方法,以便支持属性强制转换的定义。如果应用的某个模型定义了 casts 关联,则它可能与基础 Eloquent 模型类上现在存在的 casts 方法冲突。

修改数据库字段

影响可能性:高

当修改字段时,现在必须显式包含更改后要保留在字段定义上的所有修饰符。任何丢失的属性都将被删除。例如,要保留 unsigneddefaultcomment 属性,在更改列时必须显式调用每个修饰符,即使这些属性已由以前的迁移分配给该字段。

比如,假设你有一个迁移,使用了 unsigneddefaultcomment 属性来创建 votes 字段:

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 中,此迁移将保留该字段上的 unsigneddefaultcomment 属性。然而,在 Laravel 11 中,迁移现在还必须包括以前在该字段上定义的所有属性。否则,它们将被丢弃:

Schema::table('users', function (Blueprint $table) {
    $table->integer('votes')
        ->unsigned()
        ->default(1)
        ->comment('The vote count')
        ->nullable()
        ->change();
});

change() 方法不会修改该字段的索引。因此你可以在修改该字段时使用索引修饰符来显式添加或者删除索引:

// Add an index...
$table->bigIncrements('id')->primary()->change();

// Drop an index...
$table->char('postal_code', 10)->unique(false)->change();

如果你不想更新应用所有现有的“更改”迁移以保留该字段的现有属性,你可以简单地压缩迁移:

php artisan schema:dump

一旦您的迁移被压缩,Laravel 将在运行任何挂起的迁移之前使用应用的 schema 文件“迁移”数据库。

浮点类型

影响可能性:高

doublefloat 迁移字段类型已被重写,以便在所有数据库中保持一致。

现在,double 字段类型创建了一个 DOUBLE 等效字段,不包含总位数和位数(小数点后的位数),这是标准的 SQL 语法。因此,你可以删除$total$places 的参数:

$table->double('amount');

float 字段类型现在创建了一个 FLOAT 等效字段,该列没有总位数和位数(小数点后的位数),但具有可选的 $precision 规范,用于将存储大小确定为 4字节单精度字段或8 字节双精度字段。因此,你可以删除 $total$places 的参数,并根据数据库文档将可选的$precision 指定为所需值:

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

unsignedDecimalunsignedDoubleunsignedFloat 方法已被移除,因为这些字段类型的 unsigned 修饰符已被 MySQL 弃用,而且在其他数据库系统中从未标准化。不过,如果你项继续让这些字段类型使用这些弃用的 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 驱动程序,以在未来受益于 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 空间类型

影响可能性:低

数据库迁移的 spatial 字段类型已被重写,以使所有数据库保持一致。因此你可以在数据库迁移中删除 pointlineStringpolygongeometryCollectionmultiPoint,multiLineStringmultiPolygonmultiPolygonZ 方法并替换成 geometry 或者 geography

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

要明确限制 MySQL、MariaDB 和 PostgreSQL 上存储在字段的值的类型或空间引用系统标识符,可以将 subtypesrid 传递给方法:

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

PostgreSQL 语法的 isGeometryprojection 字段修饰符也被相应地移除。

Doctrine DBAL 移除

影响可能性:低

以下与 Doctrine DBAL 相关的类和方法列表已删除。Laravel 不再依赖于此包,注册自定义 Doctrines 类型对于正确创建和更改以前需要自定义类型的各种字段类型不再是必要的:

  • 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 在应用的 database 数据库配置文件中注册自定义 Doctrine 类型。

如果您以前使用 Doctrine DBAL 检查数据库及其相关表,则可以使用 Laravel 的新原生 schema 方法(Schema::getTables(), Schema::getColumns(), Schema::getIndexes(), Schema::getForeignKeys() 等)。

弃用 Schema 方法

影响可能性:非常低

基于 Doctrine 的 Schema::getAllTables()Schema::getAllViews()Schema::getAllTypes() 方法已被移除,取而代之的是 Schema::getTables()Schema::getViews()Schema::getTypes() 方法。

当使用 PostgreSQL 和 SQL Server 时,新的 schema 方法都不接受第三方引用(比如 database.schema.table。因此,你应该使用 connection() 来声明数据库来替代:

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

Schema Builder getColumnType() 方法

影响可能性:非常低

Schema::getColumnType() 方法现在返回的是戈丁字段的实际类型,不再是 Doctrine DBAL 的等效类型。

数据库连接接口

影响可能性:非常低

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

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

Date

Carbon 3

影响可能性:中

Laravel 11 支持 Carbon 2 和 Carbon 3。Carbon 是一个日期操作库,被 Laravel 和整个生态系统的包广泛使用。如果你安装了 Carbon 3,应该查看 Carbon 的更新日志。

Mail

Mailer Contract

影响可能性:非常低

Illuminate\Contracts\Mail\Mailer contract 接收了一个新的 sendNow 方法。如果你的应用或包手动实现了该 contract,你应该将新增的 sendNow 添加到实现中:

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

发布服务提供者到应用中

影响可能性:非常低

如果你编写了一个 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);

队列

BatchRepository 接口

影响可能性:非常低

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

public function rollBack();

数据库交易中的同步任务(Job)

影响可能性:非常低

此前,同步任务(使用 sync 队列驱动的任务)将会立即执行,尽管队列连接的 after_commit 配置项设置为 true 还是任务调用了 afterCommit 方法。

在 Laravel 11 中,同步队列任务现在将“尊重”队列连接或任务的“after commit”配置。

限流

每秒限流

影响可能性:中

Laravel 11 支持每秒速率限制,而不是限制为每分钟颗粒度。你应该注意与此变化相关的各种潜在的破坏性变化。

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

new GlobalLimit($attempts, 2 * 60);

Limit 类构造函数现在接受秒而非分钟。该类的所有文档化用法都仅限于静态构造函数,如 Limit::perMinuteLimit::perSecond。但是,如果手动实例化此类,则应更新应用,以便为类的构造函数提供秒:

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

Limit 类的 decayMinutes 属性已被重命名为 decaySeconds 并用秒替代了分钟。

Illuminate\Queue\Middleware\ThrottlesExceptionsIlluminate\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 的其他破坏性更新请查看完整的 Cashier Stripe 升级指南

Spark (Stripe)

Spark Stripe 更新

影响可能性:高

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

Spark Stripe 5.0 不再从它自己的迁移目录中自动加载迁移。因此,你应该运行如下命令将 Spark Stripe 的迁移发布到你的应用中:

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

Spark Stripe 的其他破坏性更新请查看完整的 Spark Stripe 升级指南

Passport

更新 Passport

影响可能性:高

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

Passport 12.0 不再从它自己的迁移目录中自动加载迁移。因此,你应该运行如下命令将 Passport 的迁移发布到你的应用中:

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

此外,密码的授权类型默认是禁用的。你可以在应用 AppServiceProviderboot 方法中调用 enablePasswordGrant 方法对其进行启用:

public function boot(): void
{
    Passport::enablePasswordGrant();
}

Sanctum

更新 Sanctum

影响可能性:高

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

Sanctum 4.0 不再从它自己的迁移目录中自动加载迁移。因此,你应该运行如下命令将 Sanctum 的迁移发布到你的应用中:

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

然后,在应用的 config/sanctum.php 配置文件中,你应该将 authenticate_sessionencrypt_cookiesvalidate_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,
],

Telescope

更新 Telescope

影响可能性:高

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

Telescope 5.0 不再从它自己的迁移目录中自动加载迁移。因此,你应该运行如下命令将 Telescope 的迁移发布到你的应用中:

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

Spatie Once 包

影响可能性:中等

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

原文地址:laravel.com/docs/11.x/upgrade

本作品采用《CC 协议》,转载必须注明作者和本文链接
Laravel Filament 中文站站长
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 6
萧晔离

正在更新中...

1个月前 评论

刚看到 twitter.com/freekmurze/status/1767... 展示的用 laravelshift 生成的 PR,感觉如果手动升级的话,并且期望是和 Laravel 11 默认新 App 目录结构基本一致的话,要做的挺多的吧,除了升级,还要清理不再需要框架文件和配置,数量有不少。

1个月前 评论
黄威

已完成升级✌

1个月前 评论
Marden (楼主) 1个月前

已完成升級 👍

雖然升級手冊建議不要調整資料夾結構,但小專案就不用管這麼多了 😆

Laravel 11 真的很讚。現在 Policy、Event Listener 還有 Notification ... 等,都不需要額外在 Service Provider 中註冊了。Laravel 會自己掃描檔案後自動註冊,貼心設計。

file

1个月前 评论
游离不2

Carbon 3.x 有点坑,注意 BC

1个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!