升级指南
从 5.5 升级到 5.5.42(安全发布)
Laravel 5.5.42 是 Laravel 的一个安全版本,建议所有用户立即升级。Laravel 5.5.42 还包含对 cookie 加密和序列化逻辑的重大更改,因此在升级应用程序时请仔细阅读以下说明。
此漏洞只有在您的应用程序加密密钥(APP_KEY
环境变量)被恶意用户访问时才可能被利用。 通常,应用程序的用户无法访问此值。但是,曾经有权限访问加密密钥的前员工可能会利用该密钥攻击您的应用程序。如果您有任何理由相信您的加密密钥已落入恶意方手中,您应始终将密钥旋转为新值。
Cookie 序列化
Laravel 5.5.42 禁用了所有 cookie 值的序列化/反序列化。由于所有 Laravel cookies 都是加密和签名的,因此通常认为 cookie 值是安全的,不会被客户端篡改。但是,如果您的应用程序的加密密钥落入恶意方手中,该方可能会使用加密密钥制作 cookie 值,并利用 PHP 对象序列化/反序列化固有的漏洞,例如在您的应用程序中调用任意类方法。
禁用所有 cookie 值的序列化将使您的应用程序的所有会话失效,用户将需要重新登录应用程序。此外,您的应用程序设置的任何其他加密 cookie 将具有无效值。因此,您可能希望向应用程序添加额外的逻辑,以验证您的自定义 cookie 值是否与您期望的值列表匹配;否则,您应丢弃它们。
配置 Cookie 序列化
由于此漏洞无法在没有访问您应用程序的加密密钥的情况下被利用,我们选择提供一种方法来重新启用加密 cookie 序列化,同时您使应用程序与这些更改兼容。要启用/禁用 cookie 序列化,您可以更改 App\Http\Middleware\EncryptCookies
中间件 的静态 serialize
属性:
/**
* 指示是否应序列化 cookie。
*
* @var bool
*/
protected static $serialize = true;
启用加密 cookie 序列化时,如果应用程序的加密密钥被恶意方访问,您的应用程序将容易受到攻击。如果您认为您的密钥可能已落入恶意方手中,您应在启用加密 cookie 序列化之前将密钥旋转为新值。
从 5.4 升级到 5.5.0
预计升级时间:1 小时
我们尝试记录每一个可能的重大更改。由于这些重大更改中的一些位于框架的晦涩部分,因此只有一部分更改可能实际影响您的应用程序。
PHP
Laravel 5.5 需要 PHP 7.0.0 或更高版本。
更新依赖项
在您的 composer.json
文件中将 laravel/framework
依赖项更新为 5.5.*
。此外,您应将 phpunit/phpunit
依赖项更新为 ~6.0
。接下来,将 filp/whoops
包添加到 composer.json
文件的 require-dev
部分,版本为 ~2.0
。最后,在 composer.json
文件的 scripts
部分,将 package:discover
命令添加到 post-autoload-dump
事件中:
"scripts": {
...
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover"
],
}
如果您正在使用 laravel/browser-kit-testing
包,您应在 composer.json
文件中将该包更新为 2.*
。
当然,不要忘记检查应用程序使用的任何第三方包,并验证您是否正在使用支持 Laravel 5.5 的正确版本。
Laravel 安装器
如果您经常通过 laravel new
使用 Laravel 安装器,您应使用 composer global update
命令更新您的 Laravel 安装器包。
Laravel Dusk
Laravel Dusk 2.0.0
已发布,以提供与 Laravel 5.5 和无头 Chrome 测试的兼容性。
Pusher
Pusher 事件广播驱动程序现在需要 Pusher SDK 的 ~3.0
版本。
Swift Mailer
Laravel 5.5 需要 Swift Mailer 的 ~6.0
版本。
Artisan
自动加载命令
在 Laravel 5.5 中,Artisan 可以自动发现命令,因此您不必手动在内核中注册它们。要利用此新功能,您应在 App\Console\Kernel
类的 commands
方法中添加以下行:
$this->load(__DIR__.'/Commands');
fire
方法
您 Artisan 命令中存在的任何 fire
方法应重命名为 handle
。
optimize
命令
随着 PHP 操作码缓存的最近改进,不再需要 optimize
Artisan 命令。您应从部署脚本中删除对此命令的任何引用,因为它将在 Laravel 的未来版本中被移除。
授权
从 Laravel 5.4 升级到 5.5 时,所有 remember_me
cookies 将失效,用户将被注销。
authorizeResource
控制器方法
当将多字模型名称传递给 authorizeResource
方法时,生成的路由段现在将是“蛇”式命名,匹配资源控制器的行为。
basic
和 onceBasic
方法
Auth::basic
和 Auth::onceBasic
现在在身份验证失败时抛出 \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
,而不是返回 Response
。默认情况下,这仍将导致向客户端发送 401 响应。但是,如果您的应用程序逻辑检查了 Auth::basic
的返回值以返回自定义响应或在身份验证失败时实现其他行为,您现在需要处理 UnauthorizedHttpException
,无论是在 catch
块中还是在应用程序的异常处理程序中。
before
策略方法
如果策略类不包含与正在检查的能力名称匹配的方法,则不会调用 before
方法。
缓存
数据库驱动
如果您正在使用数据库缓存驱动,您应在首次部署升级后的 Laravel 5.5 应用程序时运行 php artisan cache:clear
。
Eloquent
belongsToMany
方法
如果您正在覆盖 Eloquent 模型上的 belongsToMany
方法,您应更新方法签名以反映新参数的添加:
/**
* 定义多对多关系。
*
* @param string $related
* @param string $table
* @param string $foreignPivotKey
* @param string $relatedPivotKey
* @param string $parentKey
* @param string $relatedKey
* @param string $relation
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function belongsToMany($related, $table = null, $foreignPivotKey = null,
$relatedPivotKey = null, $parentKey = null,
$relatedKey = null, $relation = null)
{
//
}
BelongsToMany getQualifiedRelatedKeyName
getQualifiedRelatedKeyName
方法已重命名为 getQualifiedRelatedPivotKeyName
。
BelongsToMany getQualifiedForeignKeyName
getQualifiedForeignKeyName
方法已重命名为 getQualifiedForeignPivotKeyName
。
模型 is
方法
如果您正在覆盖 Eloquent 模型的 is
方法,您应从方法中移除 Model
类型提示。这允许 is
方法接收 null
作为参数:
/**
* 确定两个模型是否具有相同的 ID 并属于同一表。
*
* @param \Illuminate\Database\Eloquent\Model|null $model
* @return bool
*/
public function is($model)
{
//
}
模型 $events
属性
模型上的 $events
属性应重命名为 $dispatchesEvents
。此更改是因为许多用户需要定义 events
关系,这与旧属性名称发生冲突。
Pivot $parent
属性
Illuminate\Database\Eloquent\Relations\Pivot
类上的受保护 $parent
属性已重命名为 $pivotParent
。
关系 create
方法
BelongsToMany
、HasOneOrMany
和 MorphOneOrMany
类的 create
方法已被修改,以为 $attributes
参数提供默认值。如果您正在覆盖这些方法,您应更新签名以匹配新定义:
public function create(array $attributes = [])
{
//
}
软删除模型
删除“软删除”模型时,模型上的 exists
属性将保持为 true
。
withCount
列格式
使用别名时,withCount
方法将不再自动在结果列名称上附加 _count
。例如,在 Laravel 5.4 中,以下查询将导致 bar_count
列被添加到查询中:
$users = User::withCount('foo as bar')->get();
然而,在 Laravel 5.5 中,将完全按照给定的别名使用。如果您希望在结果列上附加 _count
,您必须在定义别名时指定该后缀:
$users = User::withCount('foo as bar_count')->get();
模型方法和属性名称
为了防止在使用数组访问时访问模型的私有属性,现在不可能拥有与属性或属性同名的模型方法。这样做将在通过数组访问($user['name']
)或 data_get
辅助函数访问模型的属性时引发异常。
异常格式
在 Laravel 5.5 中,所有异常,包括验证异常,都会被异常处理程序转换为 HTTP 响应。此外,JSON 验证错误的默认格式已更改。新格式符合以下约定:
{
"message": "给定的数据无效。",
"errors": {
"field-1": [
"错误 1",
"错误 2"
],
"field-2": [
"错误 1",
"错误 2"
],
}
}
然而,如果您希望保持 Laravel 5.4 JSON 错误格式,您可以将以下方法添加到 App\Exceptions\Handler
类中:
use Illuminate\Validation\ValidationException;
/**
* 将验证异常转换为 JSON 响应。
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Validation\ValidationException $exception
* @return \Illuminate\Http\JsonResponse
*/
protected function invalidJson($request, ValidationException $exception)
{
return response()->json($exception->errors(), $exception->status);
}
JSON 身份验证尝试
此更改还影响通过 JSON 进行的身份验证尝试的验证错误格式。在 Laravel 5.5 中,JSON 身份验证失败将返回遵循上述新格式约定的错误消息。
关于表单请求的说明
如果您正在自定义单个表单请求的响应格式,您现在应覆盖该表单请求的 failedValidation
方法,并抛出包含自定义响应的 HttpResponseException
实例:
use Illuminate\Http\Exceptions\HttpResponseException;
/**
* 处理验证失败尝试。
*
* @param \Illuminate\Contracts\Validation\Validator $validator
* @return void
*
* @throws \Illuminate\Validation\ValidationException
*/
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(..., 422));
}
文件系统
files
方法
Illuminate\Filesystem\Filesystem
类的 files
方法已更改其签名以添加 $hidden
参数,现在返回 SplFileInfo
对象数组,类似于 allFiles
方法。以前,files
方法返回字符串路径名数组。新签名如下:
public function files($directory, $hidden = false)
邮件
未使用的参数
未使用的 $data
和 $callback
参数已从 Illuminate\Contracts\Mail\MailQueue
合同的 queue
和 later
方法中移除:
/**
* 将新的电子邮件消息排队发送。
*
* @param string|array|MailableContract $view
* @param string $queue
* @return mixed
*/
public function queue($view, $queue = null);
/**
* 在 (n) 秒后将新的电子邮件消息排队发送。
*
* @param \DateTimeInterface|\DateInterval|int $delay
* @param string|array|MailableContract $view
* @param string $queue
* @return mixed
*/
public function later($delay, $view, $queue = null);
队列
dispatch
辅助函数
如果您希望调度一个立即运行并从 handle
方法返回值的作业,您应使用 dispatch_now
或 Bus::dispatchNow
方法来调度作业:
use Illuminate\Support\Facades\Bus;
$value = dispatch_now(new Job);
$value = Bus::dispatchNow(new Job);
请求
all
方法
如果您正在覆盖 Illuminate\Http\Request
类的 all
方法,您应更新方法签名以反映新的 $keys
参数:
/**
* 获取请求的所有输入和文件。
*
* @param array|mixed $keys
* @return array
*/
public function all($keys = null)
{
//
}
has
方法
$request->has
方法现在即使输入值为空字符串或 null
也会返回 true
。添加了一个新的 $request->filled
方法,提供 has
方法的先前行为。
intersect
方法
intersect
方法已被移除。您可以在调用 $request->only
时使用 array_filter
来复制此行为:
return array_filter($request->only('foo'));
only
方法
only
方法现在只会返回请求负载中实际存在的属性。如果您希望保留 only
方法的旧行为,您可以使用 all
方法代替。
return $request->all('foo');
request()
辅助函数
request
辅助函数将不再检索嵌套键。如果需要,您可以使用请求的 input
方法来实现此行为:
return request()->input('filters.date');
测试
身份验证断言
一些身份验证断言已重命名,以便与框架的其他断言更好地保持一致:
seeIsAuthenticated
重命名为assertAuthenticated
。dontSeeIsAuthenticated
重命名为assertGuest
。seeIsAuthenticatedAs
重命名为assertAuthenticatedAs
。seeCredentials
重命名为assertCredentials
。dontSeeCredentials
重命名为assertInvalidCredentials
。
邮件伪造
如果您正在使用 Mail
伪造来确定在请求期间是否排队了可邮寄的内容,您现在应使用 Mail::assertQueued
而不是 Mail::assertSent
。此区别允许您专门断言邮件已排队进行后台发送,而不是在请求期间发送。
Tinker
Laravel Tinker 现在支持在引用应用程序类时省略命名空间。此功能需要优化的 Composer 类映射,因此您应在 composer.json
文件的 config
部分中添加 optimize-autoloader
指令:
"config": {
...
"optimize-autoloader": true
}
翻译
LoaderInterface
Illuminate\Translation\LoaderInterface
接口已移至 Illuminate\Contracts\Translation\Loader
。
验证
验证器方法
所有验证器的验证方法现在都是 public
而不是 protected
。
视图
动态“with”变量名
在允许动态 __call
方法与视图共享变量时,这些变量将自动使用“驼峰”命名。例如,给定以下内容:
return view('pool')->withMaximumVotes(100);
可以在模板中像这样访问 maximumVotes
变量:
{{ $maximumVotes }}
@php
Blade 指令
@php
blade 指令不再接受内联标签。相反,请使用指令的完整形式:
@php
$teamMember = true;
@endphp
杂项
我们还鼓励您查看 laravel/laravel
GitHub 仓库 中的更改。虽然其中许多更改不是必需的,但您可能希望使这些文件与您的应用程序保持同步。这些更改中的一些将在本升级指南中介绍,但其他更改,例如对配置文件或注释的更改,将不会介绍。您可以轻松地使用 GitHub 比较工具 查看更改,并选择哪些更新对您来说很重要。