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属性来访问响应构建器。
返回集合数组
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
看下面的图
返回的数据
{
"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);
看下数据
状态码不在数据中,而是在图片的右上角,什么情况???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"