Yii2.0 初识 RESTful Serializer
2016-05-08 14:17
531 查看
当RESTful API响应中包含一个资源时,该资源需要序列化成一个字符串。 Yii将这个过程分成两步,首先,资源会被yii\rest\Serializer转换成数组,
然后,该数组会通过yii\web\ResponseFormatterInterface根据请求格式(如JSON, XML)被序列化成字符串。当开发一个资源类时应重点关注第一步。
所以打开Yii框架下的vendor/yiisoft/yii2/rest/Serializer.php
变量$fieldsParam对应的是是RESTful风格中的yii\base\Model::fields()或者yii\db\ActiveRecord::fields()方法的返回值结果为一个键值对数组
例如:
那么对应的当该资源被请求时返回的将是:
如果对应的模型层中没有实现yii\base\Model::fields()或者yii\db\ActiveRecord::fields()方法,则会默认返回所有定义的字段。
变量$expandParam对应的是yii\db\Model::extraFields() 和 yii\db\ActiveRecord::extraFields()
其中前者返回空值,后者返回关联模型中定义的字段键值对数组,实现方法与yii\base\Model::fields()或者yii\db\ActiveRecord::fields()相同。
变量$totalCountHeader当请求资源时如果设置了分页,那么$totalCountHeader对应资源请求中的总的记录数量。
变量$pageCountHeader当请求资源时如果设置了分页,那么$pageCountHeader对应资源请求中的分页总数。
变量$currentPageHeader当请求资源时如果设置了分页,那么$currentPageHeader对应资源请求中的当前的页码。
变量$perPageHeader当请求资源时如果设置了分页,那么$perPageHeader对应资源请求中每一页的记录数量。
变量$collectionEnvelope,当发出一个资源请求,其中包括了对分页的要求或者对于关联操作进行的设置,那么$collectionEnvelope就会有对应的值。
首先是返回的关联操作,统一的是以资源请求的url形式进行返回的,声明的时候会有譬如最典型的返回一个self链接:
那么在我们得到的资源中将会有:
增加了一个_links标记 其中包括了我们在添加的yii\db\ActiveRecord::getLinks()中添加的url,而这个标签内的内容恰好是变量$linksEnvelope对应的,如果设置了分页那么类似_links标记,还会增加一个_meta标记由$metaEnvelope对应:
对于变量的解释就到这里,接下来是对方法部分的解释。
init()方法:
每次初始化时会初始化$request和$response的值,这两个变量的实现参考vendor/yiisoft/yii2/web/Request.php
和vendor/yiisoft/yii2/web/Respense.php 就是对数据的接收的返回的解析和封装,这里不做赘述。
serialize()方法:
这一步是对数据进行序列化,将数据格式统一处理为标准的RESTful的数据格式,便于开发者操作处理。
首先看是第一个条件,判断了$data是否为符合要求的数据,此处调用的yii\base\Model::hasErrors()方法的代码如下:
当传入数据没有属性,或者数据有属性是否存在不符(通过数据层中实现的rules()方法检验)。
如果数据符合要求则会进入下面的序列化阶段,如果传入的数据为键值对那么使用serializeModel()方法:
首先用yii2/web/Request::getIsHead()方法来判断当前的请求是否为HEAD请求是的话不返回信息,如果不是则通过getRequestedFields()方法对数据进行序列化,代码如下:
首先调用yii2/web/Request::get()方法
去掉请求中的空格并且返回非空部分作为标签名。然后由serialize()返回该值。
如果传入的数据类型是根据DataProviderInterface接口实现的,那么则需要根据传入的分页信息对数据进行处理。
关于Yii的Arrayable接口,详情请见官方文档
然后,该数组会通过yii\web\ResponseFormatterInterface根据请求格式(如JSON, XML)被序列化成字符串。当开发一个资源类时应重点关注第一步。
所以打开Yii框架下的vendor/yiisoft/yii2/rest/Serializer.php
public $fieldsParam = 'fields'; public $expandParam = 'expand'; public $totalCountHeader = 'X-Pagination-Total-Count'; public $pageCountHeader = 'X-Pagination-Page-Count'; public $currentPageHeader = 'X-Pagination-Current-Page'; public $perPageHeader = 'X-Pagination-Per-Page'; public $collectionEnvelope; public $linksEnvelope = '_links'; public $metaEnvelope = '_meta'; public $request; public $response;
变量$fieldsParam对应的是是RESTful风格中的yii\base\Model::fields()或者yii\db\ActiveRecord::fields()方法的返回值结果为一个键值对数组
例如:
public function fields(){
return [
// 字段名和属性名相同
'id',
// 字段名为"email", 对应的属性名为"email_address"
'email' => 'email_address',
// 字段名为"name", 值由一个PHP回调函数定义
'name' => function ($model) {
return $model->first_name . ' ' . $model->last_name;
},
];}
那么对应的当该资源被请求时返回的将是:
[
// 字段名和属性名相同
'id',
// 字段名为"email", 对应的属性名为"email_address"
'email' => 'email_address',
// 字段名为"name", 值由一个PHP回调函数定义
'name' => function ($model) {
return $model->first_name . ' ' . $model->last_name;
},
]
如果对应的模型层中没有实现yii\base\Model::fields()或者yii\db\ActiveRecord::fields()方法,则会默认返回所有定义的字段。
变量$expandParam对应的是yii\db\Model::extraFields() 和 yii\db\ActiveRecord::extraFields()
其中前者返回空值,后者返回关联模型中定义的字段键值对数组,实现方法与yii\base\Model::fields()或者yii\db\ActiveRecord::fields()相同。
变量$totalCountHeader当请求资源时如果设置了分页,那么$totalCountHeader对应资源请求中的总的记录数量。
变量$pageCountHeader当请求资源时如果设置了分页,那么$pageCountHeader对应资源请求中的分页总数。
变量$currentPageHeader当请求资源时如果设置了分页,那么$currentPageHeader对应资源请求中的当前的页码。
变量$perPageHeader当请求资源时如果设置了分页,那么$perPageHeader对应资源请求中每一页的记录数量。
变量$collectionEnvelope,当发出一个资源请求,其中包括了对分页的要求或者对于关联操作进行的设置,那么$collectionEnvelope就会有对应的值。
首先是返回的关联操作,统一的是以资源请求的url形式进行返回的,声明的时候会有譬如最典型的返回一个self链接:
class User extends ActiveRecord implements Linkable{
public function getLinks()
{
return [
Link::REL_SELF => Url::to(['user/view', 'id' => $this->id], true),
];
}
}
那么在我们得到的资源中将会有:
{
"id": 100,
"email": "user@example.com",
// ...
"_links" => {
"self": {
"href": "https://example.com/users/100"
}
}
}
增加了一个_links标记 其中包括了我们在添加的yii\db\ActiveRecord::getLinks()中添加的url,而这个标签内的内容恰好是变量$linksEnvelope对应的,如果设置了分页那么类似_links标记,还会增加一个_meta标记由$metaEnvelope对应:
'_meta' => {
// meta information as returned by Pagination::toArray()
'totalCount' => 100,
'pageCount' => 5,
'currentPage' => 1,
'perPage' => 20,
}
对于变量的解释就到这里,接下来是对方法部分的解释。
init()方法:
public function init()
{
if ($this->request === null) {
$this->request = Yii::$app->getRequest();
}if ($this->response === null) {
$this->response = Yii::$app->getResponse();
}}
每次初始化时会初始化$request和$response的值,这两个变量的实现参考vendor/yiisoft/yii2/web/Request.php
和vendor/yiisoft/yii2/web/Respense.php 就是对数据的接收的返回的解析和封装,这里不做赘述。
serialize()方法:
public function serialize($data)
{
if ($data instanceof Model && $data->hasErrors()) {
return $this->serializeModelErrors($data);
} elseif ($data instanceof Arrayable) {
return $this->serializeModel($data);
} elseif ($data instanceof DataProviderInterface) {
return $this->serializeDataProvider($data);
} else {
return $data;
}}
这一步是对数据进行序列化,将数据格式统一处理为标准的RESTful的数据格式,便于开发者操作处理。
首先看是第一个条件,判断了$data是否为符合要求的数据,此处调用的yii\base\Model::hasErrors()方法的代码如下:
public function hasErrors($attribute = null)
{
return $attribute === null ? !empty($this->_errors) : isset($this->_errors[$attribute]);
}
当传入数据没有属性,或者数据有属性是否存在不符(通过数据层中实现的rules()方法检验)。
如果数据符合要求则会进入下面的序列化阶段,如果传入的数据为键值对那么使用serializeModel()方法:
protected function serializeModel($model)
{
if ($this->request->getIsHead()) {
return null;
} else {
list ($fields, $expand) = $this->getRequestedFields();
return $model->toArray($fields, $expand);
}}
首先用yii2/web/Request::getIsHead()方法来判断当前的请求是否为HEAD请求是的话不返回信息,如果不是则通过getRequestedFields()方法对数据进行序列化,代码如下:
protected function getRequestedFields()
{
$fields = $this->request->get($this->fieldsParam);
$expand = $this->request->get($this->expandParam);
return [
preg_split('/\s*,\s*/', $fields, -1, PREG_SPLIT_NO_EMPTY),
preg_split('/\s*,\s*/', $expand, -1, PREG_SPLIT_NO_EMPTY),
];
}
首先调用yii2/web/Request::get()方法
public function get($name = null, $defaultValue = null)
{
if ($name === null) {
return $this->getQueryParams();
} else {
return $this->getQueryParam($name, $defaultValue);
}}
public function getQueryParam($name, $defaultValue = null)
{
$params = $this->getQueryParams();
return isset($params[$name]) ? $params[$name] : $defaultValue;
}
去掉请求中的空格并且返回非空部分作为标签名。然后由serialize()返回该值。
如果传入的数据类型是根据DataProviderInterface接口实现的,那么则需要根据传入的分页信息对数据进行处理。
关于Yii的Arrayable接口,详情请见官方文档
相关文章推荐
- matplotlib知识点整理
- PHP 查询练习
- PHP 查询
- ThinkPHP的URL优化
- PHP 函数整理 (用过的)
- Yii2.0 RESTful Web服务(2)
- PHP中split()和explode()的区别
- ThinkPHP函数详解:M方法
- ThinkPHP3.1.3的单字母函数汇总
- Vsftp虚拟用户配置
- php组合
- php trait
- PHP实现简单数字分页效果
- php中session的用法
- php中excel控件导出时查询字段及备注
- thinkphp集成系列之短信验证码、订单通知
- thinkphp集成系列之短信验证码、订单通知
- thinkphp集成系列之短信验证码、订单通知
- Ubuntu编译安装PHP7
- Ubuntu为已经安装的PHP7单独编译mysqli