Responses 响应

Dingo API 主要在于处理接受客户端的request请求,以及按规范返回数据给客户端,API 默认会将返回数据以JSON的格式返回,我们也可以定义多样式的返回格式,主要取决于你自己(其中Transformer就是给返回数据做处理用的),还有前面说的fractal这个东东,Transformer和fractal的关联和区别在哪里,可以先看下[龙爷]发的这个连接:
http://fractal.thephpleague.com/simple-example/

最简单的数据返回可以从你的controllers中使用一个数组或者是一个对象来返回,并不是每一个对象都能够正确的返回,所以要确保它们实现了ArrayObject或者Illuminate\Support\Contracts\ArrayableInterface接口:怎么实现???

class UserController
{
    public function index()
    {
        return User::all();
    }
}

上面这样写默认返回的是json数组,如果dd(User::all()); 数据类型是对象的集合,而 return User::all(); 会在返回的时候自动格式化。

[{"id": 2,
"name": "zhoujiping",
"email": "zhoujiping@zhoujiping.com",
"created_at": "2016-05-31 03:38:48",
"updated_at": "2016-05-31 03:40:22"
},
{"id": 3,
"name": "kuker",
"email": "kuker@qq.com",
"created_at": "2016-05-31 03:39:59",
"updated_at": "2016-05-31 03:39:59"
}
]
// return 会自动将collection 转成json数组

下面是返回一个对象

class UserController
{
    public function index()
    {
        return User::first();
    }
}

下面是得到的数据:

{"id": 2,
"name": "zhoujiping",
"email": "zhoujiping@zhoujiping.com",
"created_at": "2016-05-31 03:38:48",
"updated_at": "2016-05-31 03:40:22"
}

我们dd(User::first()); 得到的是一个User对象,使用return, 则会自动将对象转成json格式。 (这个return成json, laravel自己默认就是这样的啊)

Dingo API会自动将响应格式化为JSON格式并设置Content-Type头为application/json。

Response Builder 响应构建器

下面的汇成一句话,就是:让你使用Dingo的response对象

response builder 提供了一套平滑的接口,可以很简单的就构建出更加符合需要的数据返回。response builder 通常和转化器(transformer)一起使用,transformer的作用如下:

我们可以通过return User::all()直接返回数据,但是更多的时候,我们需要对数据库提取的数据进行过滤或者转化才会返回,或者我们不想直接暴露数据库表字段,比如说要返回成下面这样,就可以用transformer

{
"user_id": 2,
"user_name": "zhoujiping",
"user_email": "zhoujiping@zhoujiping.com",
// "created_at": "2016-05-31 03:38:48", 
// "updated_at": "2016-05-31 03:40:22"
}

要想使用Dingo的 response, 必须在控制器中调用Dingo\Api\Routing\Helpers这个trait, 因为每一个api的controller都需要用到这个trait, 所以我们可以建立一个BaseController,用这个BaseController引入trait,然后别的controller来继承这个BaseController

use Dingo\Api\Routing\Helpers;
use Illuminate\Routing\Controller;

class BaseController extends Controller
{
    use Helpers;
}

现在可以定义一个继承自该控制器的控制器,在这些控制器中可以通过$response属性来访问响应构建器。

namespace App\Api\Controllers; 才行,上面我写错了
namespace App\Api\Controllers; 才行,图上我写错了

返回集合数组

class UsersController extends BaseController
{
    public function index()
    {
        $user = User::all();

        return $this->response->array($user->toArray());
    }
}

返回数据如下:

[{"id": 2,
"name": "zhoujiping",
"email": "zhoujiping@zhoujiping.com",
"created_at": "2016-05-31 03:38:48",
"updated_at": "2016-05-31 03:40:22"
},
{"id": 3,
"name": "kuker",
"email": "kuker@qq.com",
"created_at": "2016-05-31 03:39:59",
"updated_at": "2016-05-31 03:39:59"
}]

返回单个对象,并在返回的时候经过转化器转化transformer

<?php

namespace App\Api\Controllers;

use App\User;
use App\Api\Transformers\UserTransformer;

class UsersController extends BaseController
{
    public function index()
    {
        $user = User::first();
        return $this->response->item($user, new UserTransformer);
    }
}

UserTransformer 看下面的图

Paste_Image.png

返回的数据

{
    "data": {
        "user_id": 2,
        "User_name": "zhoujiping",
        "User_email": "zhoujiping@zhoujiping.com"
    }
}

返回对象集合,结合transformer

如果不需要用transformer处理,那就用上面的array返回就行

<?php

namespace App\Api\Controllers;

use App\User;
use App\Api\Transformers\UserTransformer;

class UsersController extends BaseController
{
    public function index()
    {
        $users = User::all();
        return $this->response->collection($users, new UserTransformer);
    }
}

返回的数据

{
    "data": [
        {
            "user_id": 2,
            "User_name": "zhoujiping",
            "User_email": "zhoujiping@zhoujiping.com"
        },
        {
            "user_id": 3,
            "User_name": "kuker",
            "User_email": "kuker@qq.com"
        }
    ]
}

对于分页的返回

<?php

namespace App\Api\Controllers;

use App\User;
use App\Api\Transformers\UserTransformer;

class UsersController extends BaseController
{
    public function index()
    {
        $users = User::paginate(1);
        return $this->response->paginator($users, new UserTransformer);
    }
}

返回如下:

{
    "data": [
        {
            "user_id": 2,
            "User_name": "zhoujiping",
            "User_email": "zhoujiping@zhoujiping.com"
        }
    ],
    "meta": {
        "pagination": {
            "total": 2,
            "count": 1,
            "per_page": 1,
            "current_page": 1,
            "total_pages": 2,
            "links": {
                "next": "http://blog-api.dev?page=2"
            }
        }
    }
}

Responding With No Content

这个搞不懂,真的是什么都没返回,连空都没有,dd($this->response->noContent()) 是一个Response 对象

return $this->response->noContent();

创建响应

return $this->response->created();

还可以将位置信息作为创建资源的第一个参数:

return $this->response->created($location);

返回空内容和创建响应,这两个不知道怎么用的???

内置的错误响应函数

// 常见的错误,用户自定义内容和错误码.
return $this->response->error('页面傻逼了,跑掉了', 404);

// A not found error with an optional message as the first parameter.
return $this->response->errorNotFound();

// A bad request error with an optional message as the first parameter.
return $this->response->errorBadRequest();

// A forbidden error with an optional message as the first parameter.
return $this->response->errorForbidden();

// An internal error with an optional message as the first parameter.
return $this->response->errorInternal();

// An unauthorized error with an optional message as the first parameter.
return $this->response->errorUnauthorized();

添加额外的响应头

return $this->response->item($user, new UserTransformer)->withHeader('zjp', 'zhoujiping');

看下头部的数据

Cache-Control →private, must-revalidate
Connection →close
Content-Type →application/json
Date →Tue, 31 May 2016 08:05:05 GMT
ETag →"87b076ffa048592f60b5b0729ce0452d"
Server →Apache/2.4.18 (Unix) PHP/5.6.19
X-Powered-By →PHP/5.6.19
zjp →zhoujiping

添加元数据

这个对于做SEO有点用

return $this->response->item($user, new UserTransformer)->addMeta('keywords', '周继平的博客, zhoujiping')->addMeta('description','我这里是描述');

看下返回的数据

{
    "data": {
        "user_id": 2,
        "User_name": "zhoujiping",
        "User_email": "zhoujiping@zhoujiping.com"
    },
    "meta": {
        "keywords": "周继平的博客, zhoujiping",
        "description": "我这里是描述"
    }
}

返回数据的时候,设定状态吗

我们之前返回的json数据,如果是成功的话,默认的status就是200,要设置的话,可以这样设置:

return $this->response->item($user, new UserTransformer)->addMeta('keywords', '周继平的博客, zhoujiping')->addMeta('description','我这里是描述')->setStatusCode(250);

看下数据

Paste_Image.png

状态码不在数据中,而是在图片的右上角,什么情况???why ????

Morphing And Morphed Events

Dingo在返回数据前会先转化(morph)响应,关于数据返回的处理,我们现在已经灰常清楚了,先通过transformer进行数据的处理,然后通过我们在config中设置的format格式,进行格式化。

我们如果对于转化有自己的需求,可以通过ResponseWasMorphed事件 和ResponseIsMorphing事件来处理

演示一下,先在app/Listeners 中创建监听器

<?php
namespace App\Listeners;

use Dingo\Api\Event\ResponseWasMorphed;

class AddPaginationLinksToResponse
{
    public function handle(ResponseWasMorphed $event)
    {
        if (isset($event->content['meta']['pagination'])) {
            $links = $event->content['meta']['pagination']['links'];

            $event->response->headers->set(
                'link',
                sprintf('<%s>; rel="next"', 
                    $links['next'])
            );
        }
    }
}

然后EventServiceProvider中注册监听

    protected $listen = [
        'Dingo\Api\Event\ResponseWasMorphed' => [
        'App\Listeners\AddPaginationLinksToResponse'
        ],
    ];

返回的数据

{
    "data": [
        {
            "user_id": 2,
            "User_name": "zhoujiping",
            "User_email": "zhoujiping@zhoujiping.com"
        }
    ],
    "meta": {
        "pagination": {
            "total": 2,
            "count": 1,
            "per_page": 1,
            "current_page": 1,
            "total_pages": 2,
            "links": {
                "next": "http://blog-api.dev?page=2"
            }
        }
    }
}

同时在头文件中也有

link →<http://blog-api.dev?page=2>; rel="next"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容