升级说明

升级说明


升级指南

  • 从 5.7 升级到 5.8.0

高影响的改变

  • 以秒为单位缓存 TTL
  • 缓存锁的安全性改进
  • Markdown 文件路径改变
  • Nexmo / Slack 通知频道改变

中等影响的改变

  • 容器生成器和标签服务
  • SQLite 版本约束
  • 在字符串和数组方面用类取代 Helpers
  • 弃用 Deferred 服务提供者
  • 符合 PSR-16 规范
  • 改进不规则复数的模型名称结尾
  • 自定义中间表模型增加自增 id 属性
  • 支持 Pheanstalk 4.0 库

从 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/Foundation/Application中.

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

认证

重置密码通知路由参数

影响可能性:低

当用户点击重置密码链接时,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/Console/Kernel契约中。如果你实现了这个接口,则应该将这个方法添加到实现类中。

容器

生成器 & 标记服务

影响可能性:中等

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

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

resolve方法

影响可能性:非常低

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

addContextualBinding方法

影响可能性:非常低

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

tagged方法

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

flush方法

影响可能性:非常低

Illuminate\Contracts\Container\Container契约增加了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\HasAttributestrait 中的originalIsEquivalent成员方法从protected改变为public

deleted_at属性的自动软删除转换

影响可能性:低

当你的 Eloquent 模型使用了Illuminate\Database\Eloquent\SoftDeletestrait 时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\ExceptionHandler契约中新增了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\Queue\Job契约中 。如果你正在实现这个 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\Routing\UrlGeneratorcontract 中。如果要调用这个接口,你应该将这个方法添加到你的实现中。

Illuminate/Routing/UrlGenerator中的cachedSchema特性

影响可能性:非常低

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

Sessions

StartSession中间件

影响可能性:非常低

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

Support

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

影响可能性:中等

所有的array_*andstr_*全局辅助函数 都被废弃。你需要直接使用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(): voidprotected 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.ghej@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网站上。