升级指南
高影响变更
中等影响变更
从 5.7 升级到 5.8.0
预计升级时间:1 小时
我们尝试记录每一个可能的重大变更。由于这些变更中的一些位于框架的偏僻部分,只有一部分变更可能实际影响您的应用程序。
更新依赖
在您的 composer.json
文件中将 laravel/framework
依赖更新为 5.8.*
。
接下来,检查您的应用程序使用的任何第三方包,并验证您是否使用了支持 Laravel 5.8 的正确版本。
Application
合约
environment
方法
影响可能性:非常低
Illuminate\Contracts\Foundation\Application
合约的 environment
方法签名已更改。如果您在应用程序中实现了此合约,您应该更新方法签名:
/**
* 获取或检查当前应用程序环境。
*
* @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
助手创建指向 password.reset
命名路由的 URL。在使用 Laravel 5.7 时,令牌被传递给 route
助手而没有显式名称,如下所示:
route('password.reset', $token);
在使用 Laravel 5.8 时,令牌被作为显式参数传递给 route
助手:
route('password.reset', ['token' => $token]);
因此,如果您定义了自己的 password.reset
路由,您应该确保它的 URI 中包含 {token}
参数。
新的默认密码长度
影响可能性:高
选择或重置密码时的密码长度要求已更改为八个字符。您应该更新应用程序中的任何验证规则或逻辑以匹配此新的八字符默认值。
如果您需要保留以前的六字符长度或不同的长度,您可以扩展 Illuminate\Auth\Passwords\PasswordBroker
类并使用自定义逻辑覆盖 validatePasswordWithDefaults
方法。
缓存
TTL 以秒为单位
影响可能性:非常高
为了允许更细粒度的过期时间,缓存项的生存时间已从分钟更改为秒。Illuminate\Cache\Repository
类及其扩展类的 put
、putMany
、add
、remember
和 setDefaultCacheTime
方法,以及每个缓存存储的 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
类的 put
、putMany
和 add
方法的 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)
方法与锁交互,则无需进行更改:
Cache::lock('foo', 10)->get(function () {
// 锁将自动安全释放...
});
但是,如果您手动调用 Cache::lock()->release()
,您必须更新代码以维护锁的实例。然后,在完成任务后,您可以在同一锁实例上调用 release
方法。例如:
if (($lock = Cache::lock('foo', 10))->get()) {
// 执行任务...
$lock->release();
}
有时,您可能希望在一个进程中获取锁并在另一个进程中释放它。例如,您可能在 Web 请求期间获取锁,并希望在由该请求触发的队列作业结束时释放锁。在这种情况下,您应该将锁的范围“所有者令牌”传递给队列作业,以便作业可以使用给定的令牌重新实例化锁:
// 在控制器中...
$podcast = Podcast::find(1);
if (($lock = Cache::lock('foo', 120))->get()) {
ProcessPodcast::dispatch($podcast, $lock->owner());
}
// 在 ProcessPodcast 作业中...
Cache::restoreLock('foo', $this->owner)->release();
如果您希望在不考虑当前所有者的情况下释放锁,可以使用 forceRelease
方法:
Cache::lock('foo')->forceRelease();
Repository
和 Store
合约
影响可能性:非常低
为了完全符合 PSR-16
,Illuminate\Contracts\Cache\Repository
合约的 put
和 forever
方法的返回值以及 Illuminate\Contracts\Cache\Store
合约的 put
、putMany
和 forever
方法的返回值已更改从 void
到 bool
。
Carbon 2.0
影响可能性:中等
Laravel 现在支持 Carbon 1 和 Carbon 2;因此,如果没有与其他包的兼容性问题,Composer 将尝试升级到 Carbon 2.0。请查看 Carbon 2.0 的迁移指南。
集合
add
方法
影响可能性:非常低
add
方法已从 Eloquent 集合类移至基础集合类。如果您扩展了 Illuminate\Support\Collection
并且您的扩展类有一个 add
方法,请确保方法签名与其父类匹配:
public function add($item);
firstWhere
方法
影响可能性:非常低
firstWhere
方法签名已更改以匹配 where
方法的签名。如果您重写了此方法,您应该更新方法签名以匹配其父类:
/**
* 通过给定的键值对获取第一个项目。
*
* @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 值。此行为与其他支持的数据库一致:
$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 开始,以不规则复数结尾的多词模型名称现在被正确复数化。
// 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
方法
影响可能性:低
loadCount
方法已添加到基础 Illuminate\Database\Eloquent\Model
类。如果您的应用程序也定义了一个 loadCount
方法,它可能会与 Eloquent 的定义冲突。
originalIsEquivalent
方法
影响可能性:非常低
Illuminate\Database\Eloquent\Concerns\HasAttributes
特性的 originalIsEquivalent
方法已更改从 protected
到 public
。
自动软删除的 deleted_at
属性转换
影响可能性:低
当您的 Eloquent 模型使用 Illuminate\Database\Eloquent\SoftDeletes
特性时,deleted_at
属性现在将自动转换为 Carbon
实例。您可以通过为该属性编写自定义访问器或手动将其添加到 casts
属性中来覆盖此行为:
protected $casts = ['deleted_at' => 'string'];
BelongsTo getForeignKey
和 getOwnerKey
方法
影响可能性:低
BelongsTo
关系的 getForeignKey
、getQualifiedForeignKey
和 getOwnerKey
方法已重命名为 getForeignKeyName
、getQualifiedForeignKeyName
和 getOwnerKeyName
,使方法名称与 Laravel 提供的其他关系一致。
环境变量解析
影响可能性:高
用于解析 .env
文件的 phpdotenv 包已发布新版本,这可能会影响 env
助手返回的结果。特别是,未引用值中的 #
字符现在将被视为注释而不是值的一部分:
以前的行为:
ENV_VALUE=foo#bar
env('ENV_VALUE'); // foo#bar
新行为:
ENV_VALUE=foo#bar
env('ENV_VALUE'); // foo
要保留以前的行为,您可以将环境值用引号括起来:
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
方法签名已更改。如果您在异常处理程序中重写了此方法,您应该更新方法签名以匹配其父类:
/**
* 渲染给定的 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
类的 send
、sendNow
、queue
、later
和 fill
方法已更改以接受 Illuminate\Contracts\Mail\Mailable
实例而不是 Illuminate\Mail\Mailable
。如果您重写了这些方法中的一些,您应该更新其签名以匹配其父类。
队列
Pheanstalk 4.0
影响可能性:中等
Laravel 5.8 提供对 Pheanstalk 队列库 ~4.0
版本的支持。如果您在应用程序中使用 Pheanstalk 库,请通过 Composer 升级您的库到 ~4.0
版本。
Job
合约
影响可能性:非常低
isReleased
、hasFailed
和 markAsFailed
方法已添加到 Illuminate\Contracts\Queue\Job
合约。如果您实现了此接口,您应该将这些方法添加到您的实现中。
Job::failed
和 FailingJob
类
影响可能性:非常低
在 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
方法现在在输入为数组时接收“完全限定”的请求输入键:
'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\UrlGenerator
的 cachedSchema
属性
影响可能性:非常低
Illuminate\Routing\UrlGenerator
的 $cachedSchema
属性名称(在 Laravel 5.7
中已弃用)已更改为 $cachedScheme
。
会话
StartSession
中间件
影响可能性:非常低
会话持久性逻辑已从 terminate()
方法移至 handle()
方法。如果您重写了这两个方法中的一个或两个,您应该更新它们以反映这些更改。
支持
优先使用字符串和数组类而非助手函数
影响可能性:中等
所有 array_*
和 str_*
全局助手函数已弃用。您应该直接使用 Illuminate\Support\Arr
和 Illuminate\Support\Str
方法。
此更改的影响被标记为 中等
,因为助手函数已移至新的 laravel/helpers 包,该包为所有全局数组和字符串函数提供了向后兼容层。
如果您选择更新 Laravel 应用程序的视图以使用基于类的方法,您应该清除可能仍在使用全局助手函数的已编译视图:
php artisan view:clear
延迟服务提供者
影响可能性:中等
服务提供者上的 defer
布尔属性用于指示提供者是否延迟已弃用。为了将服务提供者标记为延迟,它应该实现 Illuminate\Contracts\Support\DeferrableProvider
合约。
只读 env
助手
影响可能性:低
以前,env
助手可以检索在运行时更改的环境变量的值。在 Laravel 5.8 中,env
助手将环境变量视为不可变的。如果您希望在运行时更改环境变量,请考虑使用可以通过 config
助手检索的配置值:
以前的行为:
dump(env('APP_ENV')); // local
putenv('APP_ENV=staging');
dump(env('APP_ENV')); // staging
新行为:
dump(env('APP_ENV')); // local
putenv('APP_ENV=staging');
dump(env('APP_ENV')); // local
测试
setUp
和 tearDown
方法
setUp
和 tearDown
方法现在需要一个 void 返回类型:
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
合约:
/**
* 获取已验证的属性和值。
*
* @return array
*/
public function validated();
如果您实现了此接口,您应该将此方法添加到您的实现中。
ValidatesAttributes
特性
影响可能性:非常低
Illuminate\Validation\Concerns\ValidatesAttributes
特性的 parseTable
、getQueryColumn
和 requireParameterCount
方法已从 protected
更改为 public
。
DatabasePresenceVerifier
类
影响可能性:非常低
Illuminate\Validation\DatabasePresenceVerifier
类的 table
方法已从 protected
更改为 public
。
Validator
类
影响可能性:非常低
Illuminate\Validation\Validator
类的 getPresenceVerifierFor
方法已更改从 protected
到 public
。
电子邮件验证
影响可能性:非常低
电子邮件验证规则现在检查电子邮件是否符合 RFC6530,使验证逻辑与 SwiftMailer 使用的逻辑一致。在 Laravel 5.7
中,email
规则仅验证电子邮件是否符合 RFC822。
因此,在使用 Laravel 5.8 时,以前被错误地认为无效的电子邮件现在将被视为有效(例如 hej@bär.se
)。通常,这应该被视为一个错误修复;但是,出于谨慎考虑,它被列为重大变更。如果您在此更改中遇到任何问题,请告知我们。
视图
getData
方法
影响可能性:非常低
getData
方法已添加到 Illuminate\Contracts\View\View
合约。如果您实现了此接口,您应该将此方法添加到您的实现中。
通知
Nexmo / Slack 通知渠道
影响可能性:高
Nexmo 和 Slack 通知渠道已提取为一方包。要在应用程序中使用这些渠道,请要求以下包:
composer require laravel/nexmo-notification-channel
composer require laravel/slack-notification-channel
杂项
我们还鼓励您查看 laravel/laravel
GitHub 仓库中的更改。虽然这些更改中的许多不是必需的,但您可能希望将这些文件与您的应用程序保持同步。这些更改中的一些将在本升级指南中介绍,但其他更改,例如配置文件或注释的更改,将不会被介绍。您可以使用 GitHub 比较工具轻松查看更改,并选择哪些更新对您来说是重要的。