Skip to content

升级指南

高影响变更

中等影响变更

从 5.7 升级到 5.8.0

预计升级时间:1 小时

exclamation

我们尝试记录每一个可能的重大变更。由于这些变更中的一些位于框架的偏僻部分,只有一部分变更可能实际影响您的应用程序。

更新依赖

在您的 composer.json 文件中将 laravel/framework 依赖更新为 5.8.*

接下来,检查您的应用程序使用的任何第三方包,并验证您是否使用了支持 Laravel 5.8 的正确版本。

Application 合约

environment 方法

影响可能性:非常低

Illuminate\Contracts\Foundation\Application 合约的 environment 方法签名已更改。如果您在应用程序中实现了此合约,您应该更新方法签名:

php
/**
 * 获取或检查当前应用程序环境。
 *
 * @param  string|array  $environments
 * @return string|bool
 */
public function environment(...$environments);

新增方法

影响可能性:非常低

bootstrapPathconfigPathdatabasePathenvironmentPathresourcePathstoragePathresolveProviderbootstrapWithconfigurationIsCacheddetectEnvironmentenvironmentFileenvironmentFilePathgetCachedConfigPathgetCachedRoutesPathgetLocalegetNamespacegetProvidershasBeenBootstrappedloadDeferredProvidersloadEnvironmentFromroutesAreCachedsetLocaleshouldSkipMiddlewareterminate 方法已添加到 Illuminate\Contracts\Foundation\Application 合约

在极不可能的情况下,如果您实现了此接口,您应该将这些方法添加到您的实现中。

认证

密码重置通知路由参数

影响可能性:低

当用户请求重置密码的链接时,Laravel 使用 route 助手创建指向 password.reset 命名路由的 URL。在使用 Laravel 5.7 时,令牌被传递给 route 助手而没有显式名称,如下所示:

php
route('password.reset', $token);

在使用 Laravel 5.8 时,令牌被作为显式参数传递给 route 助手:

php
route('password.reset', ['token' => $token]);

因此,如果您定义了自己的 password.reset 路由,您应该确保它的 URI 中包含 {token} 参数。

新的默认密码长度

影响可能性:高

选择或重置密码时的密码长度要求已更改为八个字符。您应该更新应用程序中的任何验证规则或逻辑以匹配此新的八字符默认值。

如果您需要保留以前的六字符长度或不同的长度,您可以扩展 Illuminate\Auth\Passwords\PasswordBroker 类并使用自定义逻辑覆盖 validatePasswordWithDefaults 方法。

缓存

TTL 以秒为单位

影响可能性:非常高

为了允许更细粒度的过期时间,缓存项的生存时间已从分钟更改为秒。Illuminate\Cache\Repository 类及其扩展类的 putputManyaddremembersetDefaultCacheTime 方法,以及每个缓存存储的 put 方法已更新为此更改行为。有关更多信息,请参阅相关 PR

如果您将整数传递给这些方法中的任何一个,您应该更新代码以确保您现在传递的是希望缓存项保留的秒数。或者,您可以传递一个 DateTime 实例,指示项目何时过期:

php
// Laravel 5.7 - 存储项目 30 分钟...
Cache::put('foo', 'bar', 30);

// Laravel 5.8 - 存储项目 30 秒...
Cache::put('foo', 'bar', 30);

// Laravel 5.7 / 5.8 - 存储项目 30 秒...
Cache::put('foo', 'bar', now()->addSeconds(30));
lightbulb

此更改使 Laravel 缓存系统完全符合 PSR-16 缓存库标准

PSR-16 合规性

影响可能性:中等

除了下面的返回值更改外,Illuminate\Cache\Repository 类的 putputManyadd 方法的 TTL 参数已更新,以更好地符合 PSR-16 规范。新行为提供了一个默认值 null,因此不指定 TTL 的调用将导致缓存项永久存储。此外,使用 TTL 为 0 或更低的缓存项将从缓存中删除。有关更多信息,请参阅相关 PR

KeyWritten 事件也已更新以反映这些更改。

锁安全性改进

影响可能性:高

在 Laravel 5.7 及更早版本中,一些缓存驱动程序提供的“原子锁”功能可能会导致锁过早释放的意外行为。

例如:客户端 A 以 10 秒的过期时间获取锁 foo客户端 A 实际上需要 20 秒来完成其任务。锁在 客户端 A 处理时间的 10 秒后由缓存系统自动释放。客户端 B 获取锁 foo客户端 A 最终完成其任务并释放锁 foo,无意中释放了 客户端 B 对锁的持有。客户端 C 现在可以获取锁。

为了减轻这种情况,锁现在生成了一个嵌入的“范围令牌”,允许框架确保在正常情况下,只有锁的正确所有者可以释放锁。

如果您使用 Cache::lock()->get(Closure) 方法与锁交互,则无需进行更改:

php
Cache::lock('foo', 10)->get(function () {
    // 锁将自动安全释放...
});

但是,如果您手动调用 Cache::lock()->release(),您必须更新代码以维护锁的实例。然后,在完成任务后,您可以在同一锁实例上调用 release 方法。例如:

php
if (($lock = Cache::lock('foo', 10))->get()) {
    // 执行任务...

    $lock->release();
}

有时,您可能希望在一个进程中获取锁并在另一个进程中释放它。例如,您可能在 Web 请求期间获取锁,并希望在由该请求触发的队列作业结束时释放锁。在这种情况下,您应该将锁的范围“所有者令牌”传递给队列作业,以便作业可以使用给定的令牌重新实例化锁:

php
// 在控制器中...
$podcast = Podcast::find(1);

if (($lock = Cache::lock('foo', 120))->get()) {
    ProcessPodcast::dispatch($podcast, $lock->owner());
}

// 在 ProcessPodcast 作业中...
Cache::restoreLock('foo', $this->owner)->release();

如果您希望在不考虑当前所有者的情况下释放锁,可以使用 forceRelease 方法:

php
Cache::lock('foo')->forceRelease();

RepositoryStore 合约

影响可能性:非常低

为了完全符合 PSR-16Illuminate\Contracts\Cache\Repository 合约的 putforever 方法的返回值以及 Illuminate\Contracts\Cache\Store 合约的 putputManyforever 方法的返回值已更改voidbool

Carbon 2.0

影响可能性:中等

Laravel 现在支持 Carbon 1 和 Carbon 2;因此,如果没有与其他包的兼容性问题,Composer 将尝试升级到 Carbon 2.0。请查看 Carbon 2.0 的迁移指南

集合

add 方法

影响可能性:非常低

add 方法已从 Eloquent 集合类移至基础集合类。如果您扩展了 Illuminate\Support\Collection 并且您的扩展类有一个 add 方法,请确保方法签名与其父类匹配:

php
public function add($item);

firstWhere 方法

影响可能性:非常低

firstWhere 方法签名已更改以匹配 where 方法的签名。如果您重写了此方法,您应该更新方法签名以匹配其父类:

php
/**
 * 通过给定的键值对获取第一个项目。
 *
 * @param  string  $key
 * @param  mixed  $operator
 * @param  mixed  $value
 * @return mixed
 */
public function firstWhere($key, $operator = null, $value = null);

控制台

Kernel 合约

影响可能性:非常低

terminate 方法已添加到 Illuminate\Contracts\Console\Kernel 合约。如果您实现了此接口,您应该将此方法添加到您的实现中。

容器

生成器和标记服务

影响可能性:中等

容器的 tagged 方法现在利用 PHP 生成器来惰性实例化具有给定标签的服务。这提供了性能改进,如果您没有利用每个标记的服务。

由于此更改,tagged 方法现在返回 iterable 而不是 array。如果您在代码中对该方法的返回值进行了类型提示,您应该确保将类型提示更改为 iterable

此外,不再可能通过其数组偏移值直接访问标记服务,例如 $container->tagged('foo')[0]

resolve 方法

影响可能性:非常低

resolve 方法现在接受一个新的布尔参数,该参数指示在实例化对象期间是否应触发/执行事件(解析回调)。如果您重写了此方法,您应该更新方法签名以匹配其父类。

addContextualBinding 方法

影响可能性:非常低

addContextualBinding 方法已添加到 Illuminate\Contracts\Container\Container 合约。如果您实现了此接口,您应该将此方法添加到您的实现中。

tagged 方法

影响可能性:低

tagged 方法签名已更改,现在返回 iterable 而不是 array。如果您在代码中对该方法的返回值进行了类型提示,您应该确保将类型提示更改为 iterable

flush 方法

影响可能性:非常低

flush 方法已添加到 Illuminate\Contracts\Container\Container 合约。如果您实现了此接口,您应该将此方法添加到您的实现中。

数据库

未引用的 MySQL JSON 值

影响可能性:低

查询构建器现在在使用 MySQL 和 MariaDB 时返回未引用的 JSON 值。此行为与其他支持的数据库一致:

php
$value = DB::table('users')->value('options->language');

dump($value);

// Laravel 5.7...
'"en"'

// Laravel 5.8...
'en'

因此,->> 操作符不再支持或必要。

SQLite

影响可能性:中等

从 Laravel 5.8 开始,支持的最旧的 SQLite 版本是 SQLite 3.7.11。如果您使用的是旧版 SQLite,您应该更新它(推荐使用 SQLite 3.8.8+)。

迁移和 bigIncrements

影响可能性:无

从 Laravel 5.8 开始,迁移存根在 ID 列上默认使用 bigIncrements 方法。以前,ID 列是使用 increments 方法创建的。

这不会影响项目中的任何现有代码;但是,请注意,外键列必须是相同类型。因此,使用 increments 方法创建的列不能引用使用 bigIncrements 方法创建的列。

Eloquent

以不规则复数结尾的模型名称

影响可能性:中等

从 Laravel 5.8 开始,以不规则复数结尾的多词模型名称现在被正确复数化

php
// Laravel 5.7...
App\Feedback.php -> feedback (正确复数化)
App\UserFeedback.php -> user_feedbacks (错误复数化)

// Laravel 5.8
App\Feedback.php -> feedback (正确复数化)
App\UserFeedback.php -> user_feedback (正确复数化)

如果您有一个错误复数化的模型,您可以通过在模型上定义 $table 属性继续使用旧表名:

php
/**
 * 与模型关联的表。
 *
 * @var string
 */
protected $table = 'user_feedbacks';

具有递增 ID 的自定义枢纽模型

如果您定义了一个使用自定义枢纽模型的多对多关系,并且该枢纽模型具有自动递增的主键,您应该确保您的自定义枢纽模型类定义了一个 incrementing 属性,并将其设置为 true

php
/**
 * 指示 ID 是否自动递增。
 *
 * @var bool
 */
public $incrementing = true;

loadCount 方法

影响可能性:低

loadCount 方法已添加到基础 Illuminate\Database\Eloquent\Model 类。如果您的应用程序也定义了一个 loadCount 方法,它可能会与 Eloquent 的定义冲突。

originalIsEquivalent 方法

影响可能性:非常低

Illuminate\Database\Eloquent\Concerns\HasAttributes 特性的 originalIsEquivalent 方法已更改protectedpublic

自动软删除的 deleted_at 属性转换

影响可能性:低

当您的 Eloquent 模型使用 Illuminate\Database\Eloquent\SoftDeletes 特性时,deleted_at 属性现在将自动转换Carbon 实例。您可以通过为该属性编写自定义访问器或手动将其添加到 casts 属性中来覆盖此行为:

php
protected $casts = ['deleted_at' => 'string'];

BelongsTo getForeignKeygetOwnerKey 方法

影响可能性:低

BelongsTo 关系的 getForeignKeygetQualifiedForeignKeygetOwnerKey 方法已重命名为 getForeignKeyNamegetQualifiedForeignKeyNamegetOwnerKeyName,使方法名称与 Laravel 提供的其他关系一致。

环境变量解析

影响可能性:高

用于解析 .env 文件的 phpdotenv 包已发布新版本,这可能会影响 env 助手返回的结果。特别是,未引用值中的 # 字符现在将被视为注释而不是值的一部分:

以前的行为:

php
ENV_VALUE=foo#bar

env('ENV_VALUE'); // foo#bar

新行为:

php
ENV_VALUE=foo#bar
env('ENV_VALUE'); // foo

要保留以前的行为,您可以将环境值用引号括起来:

php
ENV_VALUE="foo#bar"

env('ENV_VALUE'); // foo#bar

有关更多信息,请参阅 phpdotenv 升级指南

事件

fire 方法

影响可能性:低

Illuminate\Events\Dispatcher 类的 fire 方法(在 Laravel 5.4 中已弃用)已被移除。 您应该使用 dispatch 方法代替。

异常处理

ExceptionHandler 合约

影响可能性:低

shouldReport 方法已添加到 Illuminate\Contracts\Debug\ExceptionHandler 合约。如果您实现了此接口,您应该将此方法添加到您的实现中。

renderHttpException 方法

影响可能性:低

Illuminate\Foundation\Exceptions\Handler 类的 renderHttpException 方法签名已更改。如果您在异常处理程序中重写了此方法,您应该更新方法签名以匹配其父类:

php
/**
 * 渲染给定的 HttpException。
 *
 * @param  \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface  $e
 * @return \Symfony\Component\HttpFoundation\Response
 */
protected function renderHttpException(HttpExceptionInterface $e);

邮件

Markdown 文件目录更改

影响可能性:高

如果您使用 vendor:publish 命令发布了 Laravel 的 Markdown 邮件组件,您应该将 /resources/views/vendor/mail/markdown 目录重命名为 /resources/views/vendor/mail/text

此外,markdownComponentPaths 方法已重命名textComponentPaths。如果您重写了此方法,您应该更新方法名称以匹配其父类。

PendingMail 类中的方法签名更改

影响可能性:非常低

Illuminate\Mail\PendingMail 类的 sendsendNowqueuelaterfill 方法已更改以接受 Illuminate\Contracts\Mail\Mailable 实例而不是 Illuminate\Mail\Mailable。如果您重写了这些方法中的一些,您应该更新其签名以匹配其父类。

队列

Pheanstalk 4.0

影响可能性:中等

Laravel 5.8 提供对 Pheanstalk 队列库 ~4.0 版本的支持。如果您在应用程序中使用 Pheanstalk 库,请通过 Composer 升级您的库到 ~4.0 版本。

Job 合约

影响可能性:非常低

isReleasedhasFailedmarkAsFailed 方法已添加到 Illuminate\Contracts\Queue\Job 合约。如果您实现了此接口,您应该将这些方法添加到您的实现中。

Job::failedFailingJob

影响可能性:非常低

在 Laravel 5.7 中,当队列作业失败时,队列工作器执行 FailingJob::handle 方法。在 Laravel 5.8 中,FailingJob 类中的逻辑已移至作业类本身的 fail 方法。因此,fail 方法已添加到 Illuminate\Contracts\Queue\Job 合约。

基础 Illuminate\Queue\Jobs\Job 类包含 fail 的实现,典型的应用程序代码不需要进行代码更改。但是,如果您构建的自定义队列驱动程序使用的作业类扩展 Laravel 提供的基础作业类,您应该在自定义作业类中手动实现 fail 方法。您可以参考 Laravel 的基础作业类作为参考实现。

此更改允许自定义队列驱动程序对作业删除过程有更多控制。

Redis 阻塞弹出

影响可能性:非常低

使用 Redis 队列驱动程序的“阻塞弹出”功能现在是安全的。以前,如果 Redis 服务器或工作器在作业检索时崩溃,队列作业可能会丢失。为了使阻塞弹出安全,为每个 Laravel 队列创建了一个带有后缀 :notify 的新 Redis 列表。

请求

TransformsRequest 中间件

影响可能性:低

Illuminate\Foundation\Http\Middleware\TransformsRequest 中间件的 transform 方法现在在输入为数组时接收“完全限定”的请求输入键:

php
'employee' => [
    'name' => 'Taylor Otwell',
],

/**
 * 转换给定的值。
 *
 * @param  string  $key
 * @param  mixed  $value
 * @return mixed
 */
protected function transform($key, $value)
{
    dump($key); // 'employee.name' (Laravel 5.8)
    dump($key); // 'name' (Laravel 5.7)
}

路由

UrlGenerator 合约

影响可能性:非常低

previous 方法已添加到 Illuminate\Contracts\Routing\UrlGenerator 合约。如果您实现了此接口,您应该将此方法添加到您的实现中。

Illuminate\Routing\UrlGeneratorcachedSchema 属性

影响可能性:非常低

Illuminate\Routing\UrlGenerator$cachedSchema 属性名称(在 Laravel 5.7 中已弃用)已更改为 $cachedScheme

会话

StartSession 中间件

影响可能性:非常低

会话持久性逻辑已从 terminate() 方法移至 handle() 方法。如果您重写了这两个方法中的一个或两个,您应该更新它们以反映这些更改。

支持

优先使用字符串和数组类而非助手函数

影响可能性:中等

所有 array_*str_* 全局助手函数已弃用。您应该直接使用 Illuminate\Support\ArrIlluminate\Support\Str 方法。

此更改的影响被标记为 中等,因为助手函数已移至新的 laravel/helpers 包,该包为所有全局数组和字符串函数提供了向后兼容层。

如果您选择更新 Laravel 应用程序的视图以使用基于类的方法,您应该清除可能仍在使用全局助手函数的已编译视图:

php
php artisan view:clear

延迟服务提供者

影响可能性:中等

服务提供者上的 defer 布尔属性用于指示提供者是否延迟已弃用。为了将服务提供者标记为延迟,它应该实现 Illuminate\Contracts\Support\DeferrableProvider 合约。

只读 env 助手

影响可能性:低

以前,env 助手可以检索在运行时更改的环境变量的值。在 Laravel 5.8 中,env 助手将环境变量视为不可变的。如果您希望在运行时更改环境变量,请考虑使用可以通过 config 助手检索的配置值:

以前的行为:

php
dump(env('APP_ENV')); // local

putenv('APP_ENV=staging');

dump(env('APP_ENV')); // staging

新行为:

php
dump(env('APP_ENV')); // local

putenv('APP_ENV=staging');

dump(env('APP_ENV')); // local

测试

setUptearDown 方法

setUptearDown 方法现在需要一个 void 返回类型:

php
protected function setUp(): void
protected function tearDown(): void

PHPUnit 8

影响可能性:可选

默认情况下,Laravel 5.8 使用 PHPUnit 7。但是,您可以选择升级到 PHPUnit 8,这需要 PHP >= 7.2。此外,请通读 PHPUnit 8 发布公告中的所有更改列表。

验证

Validator 合约

影响可能性:非常低

validated 方法已添加到 Illuminate\Contracts\Validation\Validator 合约

php
/**
 * 获取已验证的属性和值。
 *
 * @return array
 */
public function validated();

如果您实现了此接口,您应该将此方法添加到您的实现中。

ValidatesAttributes 特性

影响可能性:非常低

Illuminate\Validation\Concerns\ValidatesAttributes 特性的 parseTablegetQueryColumnrequireParameterCount 方法已从 protected 更改为 public

DatabasePresenceVerifier

影响可能性:非常低

Illuminate\Validation\DatabasePresenceVerifier 类的 table 方法已从 protected 更改为 public

Validator

影响可能性:非常低

Illuminate\Validation\Validator 类的 getPresenceVerifierFor 方法已更改protectedpublic

电子邮件验证

影响可能性:非常低

电子邮件验证规则现在检查电子邮件是否符合 RFC6530,使验证逻辑与 SwiftMailer 使用的逻辑一致。在 Laravel 5.7 中,email 规则仅验证电子邮件是否符合 RFC822

因此,在使用 Laravel 5.8 时,以前被错误地认为无效的电子邮件现在将被视为有效(例如 hej@bär.se)。通常,这应该被视为一个错误修复;但是,出于谨慎考虑,它被列为重大变更。如果您在此更改中遇到任何问题,请告知我们

视图

getData 方法

影响可能性:非常低

getData 方法已添加到 Illuminate\Contracts\View\View 合约。如果您实现了此接口,您应该将此方法添加到您的实现中。

通知

Nexmo / Slack 通知渠道

影响可能性:高

Nexmo 和 Slack 通知渠道已提取为一方包。要在应用程序中使用这些渠道,请要求以下包:

php
composer require laravel/nexmo-notification-channel
composer require laravel/slack-notification-channel

杂项

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