使用 Dingo API 扩展包快速构建 Laravel RESTful API(六) —— 转化器及响应构建器的高级使用

栏目: PHP · 发布时间: 5年前

内容简介:除了我们上篇教程介绍的一些基本使用之外,还可以通过传递额外的参数实现一些更高级的转化器功能。我们可以在响应构建器的但是这个功能只有在 Fractal 的序列化器为

转化器的高级功能

除了我们上篇教程介绍的一些基本使用之外,还可以通过传递额外的参数实现一些更高级的转化器功能。

资源键

我们可以在响应构建器的 itemcollectionpaginator 方法传入一个参数数组作为第三个参数,在这个数组中,可以通过 key 传入 Fractal 资源的类型标识:

return $this->item($task, new TaskTransformer, ['key' => 'task']);

但是这个功能只有在 Fractal 的序列化器为 JsonApiSerializer 时才有效。关于 Fractal 系列化器的设置我们下面会提到。

使用回调

Fractal 转化层允许你注册一个创建资源之后触发的回调,这个回调接收 League\Fractal\Resource\Item 或者 League\Fractal\Resource\Collection 资源作为第一个参数, League\Fractal\Manager 实例作为第二个参数,在这个回调函数中我们可以自定义序列化器、设置游标、以及其它与 Fractal 交互的功能。

设置序列化器

比如我们设置序列化器可以这么做(默认使用的序列化器是 DataArraySerializer ):

// 引入命名空间
use League\Fractal\Serializer\JsonApiSerializer;

$task = Task::findOrFail($id);
return $this->response->item($task, new TaskTransformer(), ['key' => 'task'], function ($resource, $fractal) {
        $fractal->setSerializer(new JsonApiSerializer());
    });

这样,我们访问对应的资源路由,返回的响应就变成了遵循 JSON-API 规范的数据格式:

使用 Dingo API 扩展包快速构建 Laravel RESTful API(六) —— 转化器及响应构建器的高级使用

同时也会应用第三个参数设置的资源键值作为返回资源的数据类型。关于 Fractal 支持的其它序列化器可以参考之前的Fractal 教程。

设置游标

此外,学院君前面介绍 Fractal 对分页数据进行处理的时候讲到,对于结果集很大的、对性能要求严苛的系统,除了分页器之外,还可以通过游标获取分页数据,同样,也可以在第四个回调函数中设置游标来转化分页数据,下面我们改写 Api\TaskControllerindex 方法实现代码如下:

public function index(Request $request)
{
    $current = $request->input('current');
    $previous = $request->input('previous');
    $limit = $request->input('limit') ? : 10;

    if ($current) {
        $tasks = Task::where('id', '>', $current)->take($limit)->get();
    } else {
        $tasks = Task::take($limit)->get();
    }

    $next = $tasks->last()->id;
    $cursor = new Cursor($current, $previous, $next, $tasks->count());

    return $this->response->collection($tasks, new TaskTransformer, [], function ($resource, $fractal) use ($cursor) {
        $resource->setCursor($cursor);
    });
}

再次访问首页路由,就可以看到通过游标转化的分页数据了:

使用 Dingo API 扩展包快速构建 Laravel RESTful API(六) —— 转化器及响应构建器的高级使用

自定义转化层

Dingo API 默认基于 Fractal 转化层实现转化器,你可以在 config/api.php 中看到这个默认配置:

'transformer' => env('API_TRANSFORMER', Dingo\Api\Transformer\Adapter\Fractal::class),

如果你不想使用 Fractal 作为转化层,可以在 Dingo API 中创建自己的转化层。要实现自定义的转化层,需要创建一个继承自 Dingo\Api\Contract\Transformer\Adapter 基类的子类,并且实现 transform 方法:

use Dingo\Api\Http\Request;
use Dingo\Api\Transformer\Binding;
use Dingo\Api\Contract\Transformer\Adapter;

class MyCustomTransformerAdapter implements Adapter
{
    public function transform($response, $transformer, Binding $binding, Request $request)
    {
        // 调用转化层对响应数据进行转化
    }
}

transform 是唯一必须实现的方法(因为基类中只声明了这个抽象方法),你也可以添加自己需要的其他方法,就像 Dingo\Api\Transformer\Adapter\Fractal 那样。 transform 方法的目的是获取 $response ,然后和 $transformer 一起传递给转化层处理,转化层处理之后会返回一个数组,最终这个数组被 transform 方法返回。如果你的转化层很简单,可以完全在这个方法中实现所有逻辑。

$bindings 参数用于支持更多特性,比如添加元数据或者允许开发者通过回调与转化层交互。

$request 参数是当前的 HTTP 请求,当你的转化层需要查询字符串参数或者其他相关数据时会用到它。

自定义转化层类定义好了之后,可以将其配置到 .envAPI_TRANSFORMER 配置项作为全局默认转化层,也可以在运行时通过如下方式动态设置:

$this->app['Dingo\Api\Transformer\Factory']->setAdapter(function ($app) {
     return new MyCustomTransformerAdapter(...);
});

自定义响应数据格式

默认情况下,Dingo API 返回的响应会自动使用 JSON 格式并设置相应的 Content-Type 头。除了 JSON 之外 Dingo 还支持 JSONP 格式,该格式会将响应封装到一个回调中,要将响应数据默认格式调整为该格式,只需要简单将配置文件 config/api.php 中的默认 JSON 格式替换成 JSONP 即可:

'defaultFormat' => env('API_DEFAULT_FORMAT', 'json'),

'formats' => [
    'json' => Dingo\Api\Http\Response\Format\Jsonp::class,
],

默认情况下回调参数默认查询字符串是 callback ,这可以通过修改 Jsonp 构造函数的第一个参数来设置:

使用 Dingo API 扩展包快速构建 Laravel RESTful API(六) —— 转化器及响应构建器的高级使用

如果查询字符串不包含任何参数将会返回 JSON 响应。当然,你还可以在运行时动态设置返回数据格式:

use Dingo\Api\Http\Response;

public function show($id)
{
    $task = Task::findOrFail($id);
    Response::addFormatter('json', new Response\Format\Jsonp);
    return $this->response->item($task, new TaskTransformer());
}

如果 Dingo 自带的 JSON 和 JSONP 格式满足不了你的需求,还可以自定义数据格式类。自定义的数据格式类需要继承自 Dingo\Api\Http\Response\Format\Format 基类,同时还要实现 formatEloquentModelformatEloquentCollectionformatArray 以及 getContentType 方法。

Morphing 和 Morphed 事件

在 Dingo API 发送响应之前会先对该响应数据进行转化(morph),这个过程包括运行所有转换器(Transformer)以及通过配置的响应数据格式发送响应。如果你需要控制响应数据如何被转化可以使用 Dingo 提供的 ResponseIsMorphing (转化前触发)和 ResponseWasMorphed (转化后触发)事件。

我们可以在 app/Listeners 目录下为上述事件创建监听器:

php artisan make:listener AddPaginationLinksToResponse

编辑 app/Listeners/AddPaginationLinksToResponse.php 代码如下:

<?php

namespace App\Listeners;

use Dingo\Api\Event\ResponseWasMorphed;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class AddPaginationLinksToResponse
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  object  $event
     * @return void
     */
    public function handle(ResponseWasMorphed $event)
    {
        if (isset($event->content['meta']['pagination'])) {
            $links = $event->content['meta']['pagination']['links'];
            $next = isset($links['next']) ? $links['next'] : null;
            $previous = isset($links['previous']) ? $links['previous'] : null;
            $event->response->headers->set(
                'link',
                sprintf('<%s>; rel="next", <%s>; rel="prev"', $next, $previous)
            );
        }
    }
}

然后通过在 EventServiceProvider 中注册事件及其对应监听器之间的映射关系来监听该事件:

use App\Listeners\AddPaginationLinksToResponse;
use Dingo\Api\Event\ResponseWasMorphed;

protected $listen = [
    ...
    ResponseWasMorphed::class => [
        AddPaginationLinksToResponse::class
    ]
];

现在所有包含分页链接的响应也会将这些链接添加到 Link 响应头。修改 Api\TaskControllerindex 方法实现代码如下:

public function index(Request $request)
{
    $limit = $request->input('limit') ? : 10;
    $tasks = Task::paginate($limit);
    return $this->response->paginator($tasks, new TaskTransformer());
}

在 Postman 中访问该方法对应路由,就可以看到相应结果:

使用 Dingo API 扩展包快速构建 Laravel RESTful API(六) —— 转化器及响应构建器的高级使用


以上所述就是小编给大家介绍的《使用 Dingo API 扩展包快速构建 Laravel RESTful API(六) —— 转化器及响应构建器的高级使用》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Security, Privacy and Commerce, 2nd Edition

Web Security, Privacy and Commerce, 2nd Edition

Simson Garfinkel / O'Reilly Media / 2002-01-15 / USD 44.95

Since the first edition of this classic reference was published, World Wide Web use has exploded and e-commerce has become a daily part of business and personal life. As Web use has grown, so have ......一起来看看 《Web Security, Privacy and Commerce, 2nd Edition》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

html转js在线工具
html转js在线工具

html转js在线工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具