升级说明

本文档最新版为 7.x,旧版本可能放弃维护,推荐阅读最新版!

升级指南

高影响的改变

中等影响的改变

从 Laravel 5.7 更新到 5.8

预计升级时间:1 小时

注:我们试图记录每一个可能发生的变化。因为大部分破坏性的变化在框架的内部,这些更改仅有一部分的更改可能影响你的应用。

更新依赖

composer.json 中,将 laravel/framework 依赖项更新为 5.8.*

接下来,检查应用程序中已安装的第三方包是否支持 Laravel 5.8,并检查已安装的版本是否正确。

应用契约

environment 方法

影响可能性:非常低

Illuminate/Contracts/Foundation/Applicationenvironment 方法的签名已修改。如果在您的应用程序中重写了这个方法,您应该更新此方法的签名:

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

新添加的方法

影响可能性:非常低

以下新添加方法 bootstrapPath, configPath, databasePath, environmentPath, resourcePath, storagePath, resolveProvider, bootstrapWith, configurationIsCached, detectEnvironment, environmentFile, environmentFilePath, getCachedConfigPath, getCachedRoutesPath, getLocale, getNamespace, getProviders, hasBeenBootstrapped, loadDeferredProviders, loadEnvironmentFrom, routesAreCached, setLocale, shouldSkipMiddleware, terminate 将会被添加到 Illuminate/Contracts/Fo....

如果你实现了这个接口,你应该将这些方法添加到实现类中。

认证

重置密码通知路由参数

影响可能性:低

当用户点击重置密码链接时,Laravel 使用 route 助手生成 URL ,以创建指向以 password.reset 命名的路由,当使用 Laravel 5.7 的时候,token 将会被传递到不带显式名称的 route 助手,比如:

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

当你使用 Laravel 5.8 时,token 作为显式参数传递给 route 助手:

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

因此,如果你要定义自己的 password.reset 路由,则它的 uri 中一定要包含一个 token 参数。

默认密码长度改变

影响可能性:低

选择或重置密码时所需的密码长度 更改为至少八个字符

缓存

TTL 以秒为单位

影响可能性:非常高

为了在存储数据时允许更精细的到期时间,缓存数据的生存时间从分改为秒。 Illuminate\Cache\Repository 类和它的扩展类的 putputManyaddremembersetDefaultCacheTime 方法,以及所有缓存存储器的 put 方法都完成了此更新。详情请看 相关的 PR

如果要向这些方法中的任何一个传递整数,请更新代码以确保保留在缓存中的数据传递的数值是秒。另外,你可以传递一个 DateTime 实例指示数据何时到期:

// 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));

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

遵循 PSR-16

影响可能性:中等

除了以上返回值有变化之外,本次升级还更新了Illuminate\Cache\Repository类中的 putputManyadd 方法的 TTL 参数,使之更符合 PSR-16 规范。新特性提供了一个默认的 null ,所以如果不指定 TTL 值,那么缓存将会永久存储不会过期。此外,如果缓存项的 TTL 为 0 或者更小,那么将会被清除。参阅 相关的 PR 获取更多信息。

KeyWritten事件基于这些变动 也进行了更新

锁安全性改善

影响可能性:高

在 Laravel 5.7 以及 Laravel 更早的版本的中,一些缓存驱动提供的“原子锁”特性,可能由于一些意外行为导致锁被提前释放。

例如: 客户端 A 获取了一个 10 秒过期的锁 foo客户端 A 实际上需要耗费 20 秒来完成它的任务。在客户端 A任务执行期间,锁被缓存系统自动释放。之后 客户端 B 获取到锁 foo。最终 客户端 A 完成了它的任务并释放掉锁 foo,但是无意中释放了 客户端 B 所持有的锁。这时候 客户端 C 又可以获取到锁。

为了缓解这种情况,现在使用嵌入的「范围令牌」生成锁,这样可以确保在正常情况下,只有锁的持有者才能释放锁。

如果你正在使用 Cache::lock()->get(Closure) 方法使用锁,则不需要进行任何更改:

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

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

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

    $lock->release();
}

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

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

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

// 在进程广播队列中…
Cache::restoreLock('foo', $this->owner)->release();

如果您想在不尊重其当前所有者的情况下释放锁定,您可以使用以下 forceRelease 方法:

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

RepositoryStore 契约

影响可能性:非常低

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

集合

firstWhere 方法

影响可能性:非常低

firstWhere 方法参数 已更改 匹配 where 方法的签名。如果要重写此方法,则应更新方法的参数来匹配其父级:

/**
 * Get the first item by the given key value pair.
 *
 * @param  string  $key
 * @param  mixed  $operator
 * @param  mixed  $value
 * @return mixed
 */
public function firstWhere($key, $operator = null, $value = null);

终端

Kernel 契约

影响可能性:非常低

terminate 方法 已经添加到 Illuminate/Contracts/Cons...。如果你实现了这个接口,则应该将这个方法添加到实现类中。

容器

生成器 &标记服务

影响可能性:中等

容器的 tagged 方法使用PHP生成器通过给定的标记惰性地实例化服务。由于这种改变,tagged 方法返回 iterable类型,而不是 数组。如果你这个方法使用了类型提示的返回值,则应确保将类型提示也更改为 iterable类型。

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

resolve 方法

影响可能性: 非常低

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

addContextualBinding 方法

影响可能性:非常低

Illuminate\Contracts\Container\Cont... addContextualBinding 方法。如果要实现此接口,则应将此方法加到你的实现中。

tagged 方法

影响可能性:低
tagged 方法现在 改为 返回 iterable 类型而不是 array 类型。如果你的代码参数有类型提示,找到所有tagged 方法提示 array 类型的地方,将类型提示改为 iterable 类型。

flush 方法

影响可能性:非常低

Illuminate\Contracts\Container\Cont... flush 方法。如果要实现此接口,则应将此方法加到你的实现中。

数据库

未被引号包围的 MySQL JSON 值

影响可能性:低

在使用 MySQL 和 MariaDB 的时候,Query 构造器返回的 JSON 值将不会使用引号包围。其他数据库将和这里的行为保持一致:

$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+)。

Eloquent

模型命名中的不规则复数结尾

影响可能性: 中等

从 Laravel 5.8 起,含有不规则复数形式结尾的复合名称模型命名 现在可以正确的进行复数化.

// 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 属性之后还是可以继续使用它的:

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

带有递增 ID 的自定义中继模型

如果你用一个自定义的中继模型定义了多对多的关系,而且这个中继模型拥有一个自增的主键,你应当确保这个自定义中继模型类中定义了一个 incrementing 属性其值为true

/**
 * 标识 ID 是否自增
 *
 * @var bool
 */
public $incrementing = true;

loadCount 方法

影响可能性:低

基础类 Illuminate\Database\Eloquent\Model 中添加了loadCount 方法。如果你的应用中也定义了 loadCount 方法,可能会和 Eloquent 中的相冲突。

originalIsEquivalent 方法

影响可能性:非常低

Illuminate\Database\Eloquent\Concerns\HasAttributes trait 中的 originalIsEquivalent 成员方法从 protected 改变为 public

deleted_at 属性的自动软删除转换

影响可能性:低

当你的 Eloquent 模型使用了 Illuminate\Database\Eloquent\SoftDeletes trait 时 deleted_at 成员属性 现将会自动转换 成为一个 Carbon 实例。你可以重写这个行为,通过为该成员属性编写你的自定义 accessor 或者手动将它添加到 casts 属性中:

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

BelongsTogetForeignKey 方法

影响可能性:低

BelongsTo 关联关系中的 getForeignKeygetQualifiedForeignKey 方法已分别重命名为 getForeignKeyNamegetQualifiedForeignKeyName,使得方法名和在 Laravel 提供的其他关联关系中保持一致。

事件

fire 方法

影响可能性:低

Illuminate/Events/Dispatcher 类中的fire 方法 (在Larevel 5.4中不赞成使用) 已经被 移除 了。
你应当使用它的替代方法 dispatch

异常处理器

ExceptionHandler 契约

影响可能性:低

Illuminate\Contracts\Debug\Exception... shouldReport 方法。 现在当你实现异常处理器的接口时,你需要同时实现此方法。

renderHttpException 方法

影响可能性:低

Illuminate\Foundation\Exceptions\Handler 类中 renderHttpException 方法的签名 有改动 。现在如果你在异常处理器中重写此方法,应当修改方法的签名以和其父类保持一致:

/**
 * 将给定的 Http 异常转换为 Http 响应。
 *
 * @参数 \Symfony\Component\HttpKernel\Exception\HttpExceptionInterface  $e
 * @返回 \Symfony\Component\HttpFoundation\Response
 */
protected function renderHttpException(HttpExceptionInterface $e);

Facades

Facade 服务解析

影响可能性:低

getFacadeAccessor 方法现在可以 只返回代表服务容器标识的字符串 ,之前该方法会返回一个对象实例。

邮件


Markdown 文件路径更改

影响可能性:高

如果你已经使用 vendor:publish 命令发布了 Laravel 的 Markdown 邮件组件,你需要将 /resources/views/vendor/mail/markdown 路径重命名为 text

并且 markdownComponentPaths 方法 已被重命名textComponentPaths 。如果你要重写这个方法,你应该更新方法名,使之与其父类一致。

PendingMail 类中的方法形参改变

影响可能性:非常低

Illuminate\Mail\PendingMail 类中的 sendsendNowqueuelaterfill 方法 已被更改 为需接收一个 Illuminate\Contracts\Mail\Mailable 实例作为参数,而不是 Illuminate\Mail\Mailable 实例。如果你要重写其中的方法,你需要更新其形参,和其父类保持一致。

队列

Pheanstalk 4.0

影响可能性:中

Laravel 5.8 提供了支持 ~4.0 发布版本的 Pheanstalk 队列。如果你正在应用中使用 Pheanstalk 库,请通过 Composer 升级你的库到 ~4.0 发布版本。

Job 契约

影响可能性:非常低

isReleasedhasFailedmarkAsFailed 方法 已被加入到 Illuminate\Contracts\Queu... 。如果你正在实现这个 interface ,你应该添加这些方法到你的实现代码中。

Job::failed & FailingJob

影响可能性:非常低

在 Laravel 5.7 中,当一个队列任务失败后,队列 worker 将执行 FailingJob::handle 方法。在 Laravel 5.8 中,FailingJob 类中的逻辑已被迁移到了 fail 方法中,该方法就定义在这个任务类中。正因如此, fail 方法被纳入了 Illuminate\Contracts\Queue\Job 契约。

Illuminate\Queue\Jobs\Job 基类包含了 fail 的实现,在常规的应用里不需要改任何代码。然而,如果你正在搭建自定义的队列驱动,起了一个任务类,该任务类 没有 继承由 Laravel 提供的任务基类,你应该在你自定义的任务类中手动实现 fail 方法。作为实现的参考,你可以查阅 Laravel 的任务基类。

这个改变允许定制队列驱动,从而在对任务删除过程获得更多的控制。

Redis Blocking Pop

影响可能性:非常低

现在使用 Redis 队列驱动的 「blocking pop」特性是安全的。在之前,如果 Redis 服务或者 worker 掉线的同时取出任务,可能造成队列中的任务丢失(小概率事件)。 为了让 blocking pops 变得安全,将给每一个 Laravel 队列创建一个新的带有 :notify 后缀的 Redis list 。

请求

TransformsRequest 中间件

影响可能性:低

现在,当请求输入是一个数组时, Illuminate\Foundation\Http\Middleware\TransformsRequest 中间件的 transform 方法将接收到「全限定」 请求输入的 key :

'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\Rout...中。如果要调用这个接口, 你应该将这个方法添加到你的实现中。

Illuminate/Routing/UrlGenerator 中的 cachedSchema 特性

影响可能性:非常低

Illuminate/Routing/UrlGenerator 中的$cachedSchema 属性(在 Laravel 5.7 中已被弃用) 已更改为 $cachedScheme

Sessions

StartSession 中间件

影响可能性:非常低

Session 的持久性逻辑已 terminate() 方法移动到 。 如果你要重写其中的方法, 则应该更新它们以反映这些更改。

Support

优先使用字符串和数组类而不是辅助函数

影响可能性: 中等

所有的 array_* and str_* 全局辅助函数 都被废弃。你需要直接使用 Illuminate\Support\ArrIlluminate\Support\Str 提供的方法。

这个调整的影响被标记为中等,因为这些辅助函数被转移到新的 laravel/helpers 扩展包中,以便更好地向后兼容。

延迟的服务提供者

影响可能性: 中等

服务提供程序的用于指示是否延迟提供程序的 defer 布尔属性已经被废弃。现在如果要将服务提供者标记为延迟的需要通过实现 Illuminate\Contracts\Support\DeferrableProvider 契约来完成。

测试

PHPUnit 8

影响可能性: 可选

默认情况下, Laravel 5.8 使用 PHPUnit 7.。不过, 你可以升级到 PHPUnit 8,但是这需要 PHP >= 7.2。更多细节请阅读 PHPUnit 8 版本声明

setUptearDown 方法现在要求返回void 类型:

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

验证

Validator 契约

影响可能性: 非常低

Illuminate\Contracts\Validation\Validator新增了 validated 方法

/**
 * 获取已验证的属性和值。
 *
 * @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 方法可见性从 protected 调整为了 public

邮箱验证

影响可能性: 非常低

邮箱验证规则现在回检测邮箱地址是否兼容 RFC5630, 使验证逻辑和 SwiftMailer 保持一致。在 Laravel 5.7, email 规则只验证邮箱地址是否兼容 RFC822

因此 当使用 Laravel 5.8时,之前认为无效的邮箱地址现在将被视为有效,如 (e.g hej@bär.se)。 通常,这被看做一个 bug 修复; 不过, 我们还是将其列到这里给你一个提醒。如果您遇到有关此更改的任何问题,请通知我们

视图

getData 方法

影响可能性: 非常低

Illuminate\Contracts\View\View 契约中新增了 getData 方法。如果你调用了这个接口, 则需要添加该方法的实现。

通知

Nexmo / Slack 通知频道

影响可能性: 高

Nexmo 和 Slack 通知频道已经被提前到官方扩展中。要在自己的应用中使用这些频道,需要安装以下扩展包:

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

其他

我们还鼓励你查看 laravel/laravel 代码仓库的更新日志。尽管其中的很多更新不是必须的,但是你可以将你的应用中的这些文件与代码仓库保持同步。其中一些更新已经在这篇升级指南中提到了,但是还有很多其他的小更新(如对配置文件或注释的更改)就不会列出。你可以通过 GitHub 比较工具 查看哪些更新对你而言更加重要。

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
上一篇 下一篇
Summer
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
贡献者:16