响应格式

当处理一个 RESTful API 请求时, 一个应用程序通常需要如下步骤
来处理响应格式:

  1. 确定可能影响响应格式的各种因素, 例如媒介类型, 语言, 版本, 等等。
    这个过程也被称为 content negotiation
  2. 资源对象转换为数组, 如在 Resources 部分中所描述的。
    通过 [[yii\rest\Serializer]] 来完成。
  3. 通过内容协商步骤将数组转换成字符串。
    [[yii\web\ResponseFormatterInterface|response formatters]] 通过
    [[yii\web\Response::formatters|response]] 应用程序
    组件来注册完成。

" class="reference-link">内容协商

Yii 提供了通过 [[yii\filters\ContentNegotiator]] 过滤器支持内容协商。RESTful API 基于
控制器类 [[yii\rest\Controller]] 在 contentNegotiator 下配备这个过滤器。
文件管理器提供了涉及的响应格式和语言。 例如, 如果一个 RESTful
API 请求中包含以下 header,

  1. Accept: application/json; q=1.0, */*; q=0.1

将会得到JSON格式的响应,如下:

  1. $ curl -i -H "Accept: application/json; q=1.0, */*; q=0.1" "http://localhost/users"
  2. HTTP/1.1 200 OK
  3. Date: Sun, 02 Mar 2014 05:31:43 GMT
  4. Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
  5. X-Powered-By: PHP/5.4.20
  6. X-Pagination-Total-Count: 1000
  7. X-Pagination-Page-Count: 50
  8. X-Pagination-Current-Page: 1
  9. X-Pagination-Per-Page: 20
  10. Link: <http://localhost/users?page=1>; rel=self,
  11. <http://localhost/users?page=2>; rel=next,
  12. <http://localhost/users?page=50>; rel=last
  13. Transfer-Encoding: chunked
  14. Content-Type: application/json; charset=UTF-8
  15. [
  16. {
  17. "id": 1,
  18. ...
  19. },
  20. {
  21. "id": 2,
  22. ...
  23. },
  24. ...
  25. ]

幕后,执行一个 RESTful API 控制器动作之前,[[yii\filters\ContentNegotiator]]
filter 将检查 Accept HTTP header 在请求时和配置 [[yii\web\Response::format|response format]]
'json'。 之后的动作被执行并返回得到的资源对象或集合,
[[yii\rest\Serializer]] 将结果转换成一个数组。最后,[[yii\web\JsonResponseFormatter]]
该数组将序列化为JSON字符串,并将其包括在响应主体。

默认, RESTful APIs 同时支持JSON和XML格式。为了支持新的格式,你应该
contentNegotiator 过滤器中配置 [[yii\filters\ContentNegotiator::formats|formats]] 属性,
类似如下 API 控制器类:

  1. use yii\web\Response;
  2. public function behaviors()
  3. {
  4. $behaviors = parent::behaviors();
  5. $behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_HTML;
  6. return $behaviors;
  7. }

formats 属性的keys支持 MIME 类型,而 values 必须在 [[yii\web\Response::formatters]]
中支持被响应格式名称。

" class="reference-link">数据序列化

正如我们上面所描述的,[[yii\rest\Serializer]] 负责转换资源的中间件
对象或集合到数组。它将对象 [[yii\base\ArrayableInterface]] 作为
[[yii\data\DataProviderInterface]]。 前者主要由资源对象实现, 而
后者是资源集合。

你可以通过设置 [[yii\rest\Controller::serializer]] 属性和一个配置数组。
例如,有时你可能想通过直接在响应主体内包含分页信息来
简化客户端的开发工作。这样做,按照如下规则配置 [[yii\rest\Serializer::collectionEnvelope]]
属性:

  1. use yii\rest\ActiveController;
  2. class UserController extends ActiveController
  3. {
  4. public $modelClass = 'app\models\User';
  5. public $serializer = [
  6. 'class' => 'yii\rest\Serializer',
  7. 'collectionEnvelope' => 'items',
  8. ];
  9. }

那么你的请求可能会得到的响应如下 http://localhost/users:

  1. HTTP/1.1 200 OK
  2. Date: Sun, 02 Mar 2014 05:31:43 GMT
  3. Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
  4. X-Powered-By: PHP/5.4.20
  5. X-Pagination-Total-Count: 1000
  6. X-Pagination-Page-Count: 50
  7. X-Pagination-Current-Page: 1
  8. X-Pagination-Per-Page: 20
  9. Link: <http://localhost/users?page=1>; rel=self,
  10. <http://localhost/users?page=2>; rel=next,
  11. <http://localhost/users?page=50>; rel=last
  12. Transfer-Encoding: chunked
  13. Content-Type: application/json; charset=UTF-8
  14. {
  15. "items": [
  16. {
  17. "id": 1,
  18. ...
  19. },
  20. {
  21. "id": 2,
  22. ...
  23. },
  24. ...
  25. ],
  26. "_links": {
  27. "self": {
  28. "href": "http://localhost/users?page=1"
  29. },
  30. "next": {
  31. "href": "http://localhost/users?page=2"
  32. },
  33. "last": {
  34. "href": "http://localhost/users?page=50"
  35. }
  36. },
  37. "_meta": {
  38. "totalCount": 1000,
  39. "pageCount": 50,
  40. "currentPage": 1,
  41. "perPage": 20
  42. }
  43. }

Controlling JSON output

The JSON response is generated by the [[yii\web\JsonResponseFormatter|JsonResponseFormatter]] class which will
use the [[yii\helpers\Json|JSON helper]] internally. This formatter can be configured with different options like
for example the [[yii\web\JsonResponseFormatter::$prettyPrint|$prettyPrint]] option, which is useful on development for
better readable responses, or [[yii\web\JsonResponseFormatter::$encodeOptions|$encodeOptions]] to control the output
of the JSON encoding.

The formatter can be configured in the [[yii\web\Response::formatters|formatters]] property of the response application
component in the application configuration like the following:

  1. 'response' => [
  2. // ...
  3. 'formatters' => [
  4. \yii\web\Response::FORMAT_JSON => [
  5. 'class' => 'yii\web\JsonResponseFormatter',
  6. 'prettyPrint' => YII_DEBUG, // use "pretty" output in debug mode
  7. 'encodeOptions' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE,
  8. // ...
  9. ],
  10. ],
  11. ],

When returning data from a database using the DAO database layer all data will be represented
as strings, which is not always the expected result especially numeric values should be represented as
numbers in JSON. When using the ActiveRecord layer for retrieving data from the database, the values for numeric
columns will be converted to integers when data is fetched from the database in [[yii\db\ActiveRecord::populateRecord()]].