一、为何要使用不同的 response 类型
现代的 web 和移动应用(对 Server 的要求)已经不仅仅满足于渲染 HTML 了。
现代的软件架构已渐渐将 UI 看成是一个客户端,客户端负责直接和用户发生交互,整个前端由服务端 API 驱动。
这种情况下 JSON 和 XML 就常常作为结构化数据的序列化和传输的载体在网络上传输,所以创建这种 response 的能力已经成为现代服务框架的必备要求。
二、response 类型
1、你可能知道,yii2 的 action 函数中需要(某种方法)"返回"结果,而不是直接 echo
return $this->render("index", [
"items" => $items,
]);
2、有个好消息是 yii2 现在可以 return 其他格式的数据,如:
数组
实现了 Arrayable 接口的对象
字符串
实现了 __toString() 方法的对象
只是不要忘了在 return 前设置 \Yii::$app->response->format 来告诉 Yii 你想要 response 的类型:
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
3、可选的类型有:
FORMAT_RAW
FORMAT_HTML
FORMAT_JSON
FORMAT_JSONP
FORMAT_XML
默认是FORMAT_HTML
三、JSON response
1、返回一个数组
public function actionIndex()
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$items = ["some", "array", "of", "data" => ["associative", "array"]];
return $items;
}
返回结果:
{
"0": "some",
"1": "array",
"2": "of",
"data": ["associative", "array"]
}
注: 如果没有设置 response 类型你会收到一个 exception
2、返回一个对象
public function actionView($id)
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$user = \app\models\User::find($id);
return $user;
}
这里的 $user 是一个 ActiveRecord 对象,而 ActiveRecord 类已实现了 Arrayable 接口,所以它可以很轻易地被转成 json
{
"id": 1,
"name": "John Doe",
"email": "john@example.com"
}
3、返回一个对象数组
public function actionIndex()
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$users = \app\models\User::find()->all();
return $users;
}
这里的 $users 就是一个 ActiveRecord 对象数组,不过在底层 yii 是通过 \yii\helpers\Json::encode() 来传输和转化数据的,所以返回的时候请小心确保数组中元素的类型
[
{
"id": 1,
"name": "John Doe",
"email": "john@example.com"
},
{
"id": 2,
"name": "Jane Foo",
"email": "jane@example.com"
},
...
]
四、XML response
1、只要把 response 的 format 改成 FORMAT_XML,,那么你就能得到 XML 类型的返回值
public function actionIndex()
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_XML;
$items = ["some", "array", "of", "data" => ["associative", "array"]];
return $items;
}
//返回 some array of associative array
2、我们同样可以把对象转成 XML
public function actionIndex()
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_XML;
$users = \app\models\User::find()->all();
return $users;
}
//返回 1 John Doe john@example.com 2 Jane Foo jane@example.com
五、定制化自己的response类型
让我们搞一个自己的 response 类型玩玩吧。为了让例子有趣点,我们打算 respond 一个 PHP 数组格式的数据。
1、定制一个 formatter
创建文件 components/PhpArrayFormatter.php
getHeaders()->set("Content-Type", "text/php; charset=UTF-8");
if ($response->data !== null) {
$response->content = "<?php\nreturn " . VarDumper::export($response->data) . ";\n";
}
}
}
2、在配置文件中注册这个 formatter
return [
// ...
"components" => [
// ...
"response" => [
"formatters" => [
"php" => "app\components\PhpArrayFormatter",
],
],
],
];
3、在 controller 里创建一个 action
public function actionTest()
{
Yii::$app->response->format = "php";
return [
"hello" => "world!",
];
}
4、执行之后的 response 是这样的
"world!",
];