2.4. 响应

未匹配的标注
本文档最新版为 2.0.0,旧版本可能放弃维护,推荐阅读最新版!

A functioning API is built upon receiving requests and returning a consumable response to the client. An API will generally return responses in an easy to consume format such as JSON. There's a number of different ways to return responses and it will largely depend on how complex your API is or will become.

The easiest way to return a consumable response is to simply return an array or object directly from your controller. Not every object can be correctly formatted though so you should ensure that it implements either the ArrayObject or the Illuminate\Support\Contracts\ArrayableInterface interface.

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

In this case our User class extends from Illuminate\Database\Eloquent\Model which means it can be formatted as an array, so we can simply return the collection of users we get from calling User::all(). Similarly you can use it return a single user.

class UserController
{
    public function show($id)
    {
        return User::findOrFail($id);
    }
}

The package will automatically format the response as JSON and set the Content-Type header to application/json.

Response Builder

The response builder provides a fluent interface to easily build a more customizable response. The response builder is generally used in conjunction with transformers.

To utilize the response builder your controllers should use the Dingo\Api\Routing\Helpers trait. To save importing and using the trait on all your controllers you can simply create a base controller that all your API controllers will extend.

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

class BaseController extends Controller
{
    use Helpers;
}

Now your controllers can simply extend this base controller. The response builder is available via the $response property on your controller. Note that all the methods below can also be used as withX should you prefer that syntax.

Some of the documentation below makes use of Transformers, be sure to read that chapter for more details.

Responding With An Array

class UserController extends BaseController
{
    public function show($id)
    {
        $user = User::findOrFail($id);

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

You can also specify a transformer for array responses.

class UserController extends BaseController
{
    public function show($id)
    {
                $setOfThings = [ 'a' => 1, 'b' => 2 ];

        return $this->response->array($setOfThings, new ArbitraryTransformer);
    }
}

Responding With A Single Item

class UserController extends BaseController
{
    public function show($id)
    {
        $user = User::findOrFail($id);

        return $this->response->item($user, new UserTransformer);
    }
}

Responding With A Collection Of Items

class UserController extends BaseController
{
    public function index()
    {
        $users = User::all();

        return $this->response->collection($users, new UserTransformer);
    }
}

Responding With Paginated Items

class UserController extends BaseController
{
    public function index()
    {
        $users = User::paginate(25);

        return $this->response->paginator($users, new UserTransformer);
    }
}

Responding With No Content

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

Responding With Created Response

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

You can also optionally provide a location for the created resource as the first paramter.

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

Responding With An Error

There's a number of different built in errors you can use to quickly generate an error response.

// A generic error with custom message and status code.
return $this->response->error('This is an 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();

Adding Additional Headers

Once you've used one of the above methods you can further customize the response by adding additional headers.

return $this->response->item($user, new UserTransformer)->withHeader('X-Foo', 'Bar');

Adding Meta Data

Some transformation layers may utilize meta data. This is useful when you need to provide extra data that's associated with the resource.

return $this->response->item($user, new UserTransformer)->addMeta('foo', 'bar');

You can also set an array of meta data instead of chaining multiple method calls.

return $this->response->item($user, new UserTransformer)->setMeta($meta);

Setting Response Status Code

return $this->response->item($user, new UserTransformer)->setStatusCode(200);

Custom Response Formats

In the configuration chapter we briefly touched on response formats. By default the package will automatically use the JSON format and set an appropriate Content-Type header. Aside from a JSON formatter there is also a JSONP formatter. This formatter will wrap the responses in a callback. To register this format you can simply swap out the default JSON formatter in the configuration file or in your bootstrap file.

'formats' => [
    'json' => 'Dingo\Api\Http\Response\Format\Jsonp'
]
Dingo\Api\Http\Response::addFormatter('json', new Dingo\Api\Http\Response\Format\Jsonp);

By default the callback parameter expected in the query string is callback, this can be changed by passing in the first parameter to the class constructor. If the query string does not contain a parameter with the name of your callback parameter it will default to a JSON response.

You can also register and use your own formatters should you need to. Your formatter should extend Dingo\Api\Http\Response\Format\Format. There following methods should be defined: formatEloquentModel, formatEloquentCollection, formatArray, and getContentType. Refer to the abstract class for more details on what each method should do or take a look at the pre-defined format classes.

Morphing And Morphed Events

Before this package sends a response it will first morph the response. This process involves running any transformers as well as sending the response through the configured formatter. If you need more control of how a response is morphed you can use the ResponseWasMorphed and ResponseIsMorphing events.

Create a listener for either event in your app/Listeners directory.

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", <%s>; rel="prev"', $links['links']['next'], $links['links']['previous'])
            );
        }
    }
}

You can then listen for the events by adding the event and your listener in your EventServiceProvider.

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

Now all responses that contain pagination links will also add these links to the Link header.

Note that this code isn't production ready and is merely a demonstration of how you can utilize the events.

← Creating API Endpoints | Errors And Error Responses →

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 7
发起讨论 只看当前版本


simaguo
Lumen 中 dingo 设置 CustomSerializer
4 个点赞 | 8 个回复 | 分享 | 课程版本 2.0.0
li603674060
BaseController 里面都写什么?
1 个点赞 | 4 个回复 | 问答 | 课程版本 2.0.0
小手冰凉
怎么使用 dingo 的成功响应
0 个点赞 | 4 个回复 | 问答 | 课程版本 2.0.0
zhangjian
UserTransformer 是啥哈
0 个点赞 | 2 个回复 | 问答 | 课程版本 2.0.0
王鲸弋
Transformer 对 item,array 为什么没反应呢?
0 个点赞 | 1 个回复 | 问答 | 课程版本 2.0.0
heibai_2018
接口响应如何返回多个值
0 个点赞 | 0 个回复 | 问答 | 课程版本 2.0.0