Yii2.0 初识 RESTful Serializer

当RESTful API响应中包含一个资源时,该资源需要序列化成一个字符串。 Yii将这个过程分成两步,首先,资源会被yii\rest\Serializer转换成数组,
然后,该数组会通过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": "[email protected]",    // ...    "_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接口,详情请见官方文档

时间: 2024-10-24 08:18:37

Yii2.0 初识 RESTful Serializer的相关文章

Yii2.0 实现RESTful风格的简单API

一.创建数据库 首先,在mysql中创建一个名为yii2basic的数据库,并创建一张名为player的表. 二.配置 1.app/config/db.php <?php return [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=yii2basic', 'username' => 'root', 'password' => '', 'charset' => 'utf8',

Yii2.0 RESTful Web服务(4)

路由 随着资源和控制器类准备,您可以使用URL如 http://localhost/index.php?r=user/create访问资源,类似于你可以用正常的Web应用程序做法. 在实践中,你通常要用美观的URL并采取有优势的HTTP动词. 例如,请求POST /users意味着访问user/create动作. 这可以很容易地通过配置urlManager应用程序组件来完成 如下所示: 'urlManager' => [ 'enablePrettyUrl' => true, 'enableSt

学习yii2.0框架(一)

Yii 是什么 Yii 是一个高性能,基于组件的 PHP 框架,用于快速开发现代 Web 应用程序.名字 Yii (读作 易)在中文里有“极致简单与不断演变”两重含义,也可看作 Yes It Is! 的缩写. Yii 最适合做什么? Yii 是一个通用的 Web 编程框架,即可以用于开发各种用 PHP 构建的 Web 应用.因为基于组件的框架结构和设计精巧的缓存支持,它特别适合开发大型应用,如门户网站.社区.内容管理系统(CMS).电子商务项目和 RESTful Web 服务等. 系统要求 Yi

Yii2.0实用功能技巧解密之——分页功能

Yii中的分页功能主要由yii\web: Linkable接口.yii\widgets: LinkPager类和yii\data: Pagination类三个组成. yii\data: Pagination 主要功能是对分页中的参数进行设置,如当前页.每页大小.总页数,总记录数等. yii\widgets: LinkPager 主要是根据yii\data: Pagination类所提供的参数生成前台页面的分页html代码. 使用:先在action里面生成分页对象,然后在前台的LinkPager中

BUG YII2.0 $ is not defined

BUG描述:$ is not defined 没有加载jquery成功 原因:Yii2.0将JS代码默认加载页面加载后 解决方案: 第一种方案:最简单方法是在 assets\AppAsset.php 中加上,页面前加载 public $jsOptions = array( 'position' => \yii\web\View::POS_HEAD ); 第二种方案:But in production you usually want the scripts to load last, and i

[moka同学笔记]三、Yii2.0课程笔记(魏曦老师教程)

关联字段增加搜索 post表关联adminuser表,通过post.author_id  adminuser.id关联,在YII2.0生成搜索,关联字段搜索时,需要输入关联字段author的id才能搜索,这不符合我们的要求,我们要求输入作者名就可以搜索出来,该作者对应的post.

PHP框架Yii2.0安装(基础版、高级版)

最近农成也是切入了yiiframework 2.0,就是安装yii2.0就花费了不少的时间,为此做了很多的弯路,特此写一篇博文来给后面学习的同学少走一点的弯路.写的不好的地方欢迎各位学习的同学们能够指点出来. yii2.0的安装,官方提供了两种的安装办法,一种是通过composer来安装,另外一种是通过跟yii1.0的办法直接下载安装包来安装.至于对于第一种composer的安装,农成就不做多余的说明了,这里有很好的安装教程.点击进去就可以看到了,为此农成就不在说了,下面就给大家详细讲讲第二种通

Yii2.0中文开发向导——高级应用程序模板

高级应用程序模板这个模板用在大型的团队开发项目中,而且后台从前台独立分离出来以便于部署在多个服务器中.由于YIi2.0的一些新的特性,这个程序模板的功能要更深一点.提供了基本的数据库的支持,注册.密码找回等功能.安装可以通过Composer来安装如果没有安装Composer,先安装 curl -s http://getcomposer.org/installer | php 然后用如下命令来获取 php composer.phar create-project --prefer-dist --s

yii2.0数据库查询修改等方法

yii2.0学习有一段时间了,给大家分享一下一些简单的查询等如何操作. 查询:(这里最前面的Test是引用的模型名) Test::find()->all();    此方法返回所有数据: 这些查询出来是对象形式,但是一般转换成数组格式: Test::find()->asArray()->all();     加上asArray()就取得数组形式的数据了,下面的自行添加. Test::findOne($id);   此方法返回 主键 id=1  的一条数据(举个例子): 条件查询:wher