2.6. Transformers
Transformers 允许你便捷地、始终如一地将对象转换为一个数组。通过使用一个 transformer 你可以对整数和布尔值,包括分页结果和嵌套关系进行类型转换。
专业术语
在这一章 "transformer" 这个词用得很多。需要注意下面的词语在使用的时候是什么意思,因为这些词贯穿了整个章节。
- 转换层 是一个类库,它负责准备和操作 transformers 。
- 一个 transformer 是一个类,它会获取原始数据并将返回一个格式化之后的标准数组。
使用 Transformers
这里有两种使用 transformers 的方法。
为一个类注册一个 Transformer
当你为一个指定的类注册一个 transformer 时,你将能够直接从你的路由中返回这个类(假设它可以变成一个数组),并且通过 transformer 自动运行。这对于那些简单的 API 来说非常有用,因为在你使用模型的地方,你可以轻而易举的从路由中返回这个模型。
app('Dingo\Api\Transformer\Factory')->register('User', 'UserTransformer');
使用响应生成器
返回 响应生成器 小节,查看如何使用。
Fractal
Fractal 是包使用的默认转换层。 它拥有许多有用的功能,可帮助您保持数据的一致性。
要使用 Fractal,建议你去它们的网站阅读文档。
自动关系预加载
当使用 Fractal 的引入功能嵌入关系的时候,你应该确保你在你的模型中定义了相同的名字。这个包会自动为你预加载这些关系,以减少查询数量。
更多配置
Fractal 被注册为默认的数据转换层,并使用默认的配置。定义嵌入的关系时,如果要自定义 include
关键词和分隔符,你必须在 service provider 或启动文件中手动实例化 Dingo\Api\Transformer\Adapter\Fractal
类。
$this->app['Dingo\Api\Transformer\Factory']->setAdapter(function ($app) {
return new Dingo\Api\Transformer\Adapter\Fractal(new League\Fractal\Manager, 'include', ',');
});
如果你正在使用 Lumen 你可以在启动文件里面这样设置。
app('Dingo\Api\Transformer\Factory')->setAdapter(function ($app) {
return new Dingo\Api\Transformer\Adapter\Fractal(new League\Fractal\Manager, 'include', ',');
});
响应生成器的高级用法
将Fractal与响应构建器一起使用通常是从控制器返回数据的最佳方法。
响应生成器上的 item
,collection
和 paginator
方法都能接收一些额外的参数用于进一步自定义 Fractal 。
资源键
return $this->item($user, new UserTransformer, ['key' => 'user']);
使用回调
Fractal 转换层允许你在创建资源后注册一个可触发的回调方法。这个回调函数接收一个 League\Fractal\Resource\Item
或者 League\Fractal\Resource\Collection
实例作为第一个参数,接收 League\Fractal\Manager
实例作为第二个参数。然后你可以使用它与资源进行更复杂的交互。
最典型的用法就是你可以在设置游标用来进行数据分页或者更改基本响应数据序列化的方式。
return $this->collection($users, new UserTransformer, [], function ($resource, $fractal) {
$resource->setCursor($cursor);
});
如果你不使用资源键参数,可以省略空数组,直接把回调方法作为第三个参数。
return $this->collection($users, new UserTransformer, function ($resource, $fractal) {
$fractal->setSerializer(new CustomSerializer);
});
自定义转换层
在 dingo/api 里,你可以轻松地自定义 Transformer 的数据格式。只需要创建一个实现了 Dingo\Api\Contract\Transformer\Adapter
接口的类并且包含 transform
方法即可:
use Dingo\Api\Http\Request;
use Dingo\Api\Transformer\Binding;
use Dingo\Api\Contract\Transformer\Adapter;
class MyCustomTransformer implements Adapter
{
public function transform($response, $transformer, Binding $binding, Request $request)
{
// 在这里可以使用你的转换层转换给出的响应
}
}
transform
方法是唯一必需的,除此之外你可以随意添加其他方法。transform
方法的目的就是获取 $response
,然后把它和 $transformer
一起发到转换层。转换层这里应该由 transform
方法返回一个数组。当然,如果转换非常简单,可直接在类内部实现转换。
$binding
参数可以让转换层具有更高级的特性,比方,增加元数据或者允许其他开发者通过回调方法和你的转换层进行交互。
$request
参数是指当前正在进行的 HTTP 请求,当你需要请求中的相关数据,这个可以派上用场。