新版特性


Laravel 5.8 在 Laravel 5.7 的基础上继续进行优化,包括引入新的 Eloquent 关联关系(远层一对一)、优化邮箱验证、基于约定的授权策略类自动注册、DynamoDB 缓存及 Session 驱动、优化任务调度器的时区配置、支持分配多个认证 guard 到广播频道、PSR-16缓存驱动规范、优化 artisan serve 命令、支持 PHPUnit 8.0、支持 Carbon 2.0、支持 Pheanstalk 4.0,以及多个 bug 修复和可用性的提升。

Eloquent HasOneThrough 关联关系

Eloquent 现在提供了对 HasOneThrough 关联类型的支持。例如,假设 Supplier 模型类与 Account 模型类之间是一对一关联,并且 Account 模型类与 AccountHistory 模型类之间也是一对一关联,那么我们说 Supplier 模型类与 AccountHistory 模型类之间可以通过 hasOneThrough 方法基于 Account 模型类建立远层的一对一关联:

/**
 * Get the account history for the supplier.
 */
public function accountHistory()
{
    return $this->hasOneThrough(AccountHistory::class, Account::class);
}

自动发现模型对应策略类

在之前版本中,每个模型类对应的授权策略类需要在应用的 AuthServiceProvider 中显式注册:

/**
 * The policy mappings for the application.
 *
 * @var array
 */
protected $policies = [
    'App\User' => 'App\Policies\UserPolicy',
];

Laravel 5.8 引入了模型类对应策略类的自动发现机制,只要模型类和策略类遵循标准的 Laravel 命名约定(在约定的命名空间及对应目录下)。也就是说,策略类都必须位于模型类所在目录的子目录 Policies 中,例如,如果模型类都位于 app 目录下,则策略类必须位于 app/Policies 目录下。此外,策略类的名称必须和模型类相匹配,并且有一个 Policy 后缀,因此,User 模型类对应的策略类就是 UserPolicy

如果你想要提供自己的策略类发现逻辑,可以使用 Gate::guessPolicyNamesUsing 方法注册自定义的回调。通常,该方法会在应用自带的服务提供者类 AuthServiceProvider 中调用:

use Illuminate\Support\Facades\Gate;

Gate::guessPolicyNamesUsing(function ($modelClass) {
    // 返回相应的策略类名称...
});

注:任何显式注册在 AuthServiceProvider 中的模型映射策略类优先级高于这种自动发现获取的策略类。

PSR-16 缓存规范

为了在存储缓存项时允许更细粒度的过期时间并遵守 PSR-16 缓存标准,我们将缓存项的有效期单位从分钟调整到秒。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));

多个广播认证 Guard

在 Laravel 之前的版本中,私有和存在广播频道通过应用的默认认证 guard 对用户进行认证。从 Laravel 5.8 开始,你可以分配多个不同的 guard 来对请求进行认证:

Broadcast::channel('channel', function() {
    // ...
}, ['guards' => ['web', 'admin']])

Token Guard 令牌哈希算法

Laravel 的 token guard 用于提供最基本的 API 认证,现在支持以 SHA-256 哈希算法对 API 令牌进行存储,这样比存储纯文本令牌更加安全。想要了解更多关于哈希令牌的细节,可以查看完整的 API 认证文档

注:当基于 Laravel 处理一个简单的、基于令牌的认证 guard 时,强烈推荐使用 Laravel Passport,它更加健壮,适用于生产环境。

优化邮箱验证

Laravel 5.8 通过 SwiftMailer 提供的 egulias/email-validator 扩展包对验证器的底层邮箱验证逻辑进行了优化。之前版本的邮箱验证逻辑偶尔会将有效的邮箱地址,如 example@bär.se 判定为无效。

默认调度器时区

Laravel 允许你使用 timezone 方法自定义调度任务的时区:

$schedule->command('inspire')
     ->hourly()
     ->timezone('America/Chicago');

不过,当每个调度任务的时区都一样时这样编写代码显得笨重和累赘,因此,你现在可以在 app/Console/Kernel.php 文件中定义一个 scheduleTimezone 方法,用来返回在所有调度任务中使用的默认时区:

/**
 * Get the timezone that should be used by default for scheduled events.
 *
 * @return \DateTimeZone|string|null
 */
protected function scheduleTimezone()
{
    return 'America/Chicago';
}

Artisan 调用优化

Laravel 允许你通过 Artisan::call 方法调用 Artisan 命令,在之前发布的版本中,命令的选项通过数组以第二个参数的方式传递到该方法:

use Illuminate\Support\Facades\Artisan;

Artisan::call('migrate:install', ['database' => 'foo']);

然而,在 Laravel 5.8 中,你可以传递整个命令,包括命令的选项,只需传递一个参数即可:

Artisan::call('migrate:install --database=foo');

测试辅助方法 mock/spy

为了让模拟对象更方便,Laravel 测试用例基类中新增了 mockspy 方法,这两个方法会自动绑定模拟类到容器中。例如:

// Laravel 5.7
$this->instance(Service::class, Mockery::mock(Service::class, function ($mock) {
    $mock->shouldReceive('process')->once();
}));

// Laravel 5.8
$this->mock(Service::class, function ($mock) {
    $mock->shouldReceive('process')->once();
});

Eloquent 资源键保留

当从路由中返回一个 Eloquent 资源集合时,Laravel 会重置集合的键以便它们以简单的数字顺序呈现:

use App\User;
use App\Http\Resources\User as UserResource;

Route::get('/user', function () {
    return UserResource::collection(User::all());
});

当使用 Laravel 5.8 时,你可以添加一个 preserveKeys 属性到资源类表明资源类的键是否保留。默认情况下,为了和之前版本的 Laravel 保持一致,这些键会被重置:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class User extends JsonResource
{
    /**
     * Indicates if the resource's collection keys should be preserved.
     *
     * @var bool
     */
    public $preserveKeys = true;
}

而如果 preserveKeys 属性值为 true 时,集合键会被保留:

use App\User;
use App\Http\Resources\User as UserResource;

Route::get('/user', function () {
    return UserResource::collection(User::all()->keyBy->id);
});

更高阶的 Eloquent 方法 orWhere

在之前版本的 Laravel 中,通过 or 查询操作符连接不同的 Eloquent 模型作用域时需要使用闭包回调:

// scopePopular and scopeActive methods defined on the User model...
$users = App\User::popular()->orWhere(function (Builder $query) {
    $query->active();
})->get();

Laravel 5.8 引入了更高阶的 orWhere 方法,允许你以方法链的方式链接作用域,而不必使用闭包:

$users = App\User::popular()->orWhere->active()->get();

Artisan Serve 命令优化

在之前版本的 Laravel 中,Artisan 的 serve 命令会在 8000 端口上提供服务,如果有一个 serve 命令已经在监听这个端口,则再次运行 artisan serve 命令会失败。从 Laravel 5.8 开始,serve 会扫描从 80008009 之间的所有有效端口,以便你可以一次运行多个 serve 命令。

Blade 文件映射

编译 Blade 模板时,Laravel 现在会添加一行注释到编译后文件的顶部,其中包含了编译前 Blade 模板文件的路径。

DynamoDB 缓存/Session 驱动

Laravel 5.8 引入了 DynamoDB 缓存和 Session 驱动,DynamoDB 是一个由 AWS 提供的无服务器 NoSQL 数据库,dynamodb 缓存的默认配置可以在 Laravel 5.8 的缓存配置文件中找到。

支持 Carbon 2.0

Laravel 5.8 提供了对日期操作库 Carbon ~2.0 版本的支持。

支持 Pheanstalk 4.0

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


点赞 取消点赞 收藏 取消收藏

<< 上一篇: 目录索引

>> 下一篇: 升级指南