mirror of
https://github.com/yiisoft/yii2.git
synced 2025-08-26 14:26:54 +08:00
REST wip.
This commit is contained in:
@ -216,7 +216,7 @@ of the object if it implements [[yii\base\ArrayableInterface]]. If an object doe
|
|||||||
an array consisting of all its public properties will be returned.
|
an array consisting of all its public properties will be returned.
|
||||||
|
|
||||||
For classes extending from [[yii\base\Model]] or [[yii\db\ActiveRecord]], besides directly overriding `toArray()`,
|
For classes extending from [[yii\base\Model]] or [[yii\db\ActiveRecord]], besides directly overriding `toArray()`,
|
||||||
you may also override the `fields()` method and/or the `expandableFields()` method to customize the data to be returned.
|
you may also override the `fields()` method and/or the `extraFields()` method to customize the data to be returned.
|
||||||
|
|
||||||
The method [[yii\base\Model::fields()]] declares a set of fields of an object that should be included in the result.
|
The method [[yii\base\Model::fields()]] declares a set of fields of an object that should be included in the result.
|
||||||
The default implementation returns all attributes of a model as the output fields. You can customize it to add,
|
The default implementation returns all attributes of a model as the output fields. You can customize it to add,
|
||||||
@ -254,7 +254,7 @@ returning the corresponding field values.
|
|||||||
You may use the `fields` query parameter to specify which fields in `fields()` should be included in the result.
|
You may use the `fields` query parameter to specify which fields in `fields()` should be included in the result.
|
||||||
If this parameter is not specified, all fields returned by `fields()` will be returned.
|
If this parameter is not specified, all fields returned by `fields()` will be returned.
|
||||||
|
|
||||||
The method [[yii\base\Model::expandableFields()]] is very similar to [[yii\base\Model::fields()]].
|
The method [[yii\base\Model::extraFields()]] is very similar to [[yii\base\Model::fields()]].
|
||||||
The difference between these methods is that the latter declares the fields that should be returned by default,
|
The difference between these methods is that the latter declares the fields that should be returned by default,
|
||||||
while the former declares the fields that should only be returned when the user specifies them in the `expand` query parameter.
|
while the former declares the fields that should only be returned when the user specifies them in the `expand` query parameter.
|
||||||
|
|
||||||
|
163
framework/base/ArrayableTrait.php
Normal file
163
framework/base/ArrayableTrait.php
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @link http://www.yiiframework.com/
|
||||||
|
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||||
|
* @license http://www.yiiframework.com/license/
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace yii\base;
|
||||||
|
|
||||||
|
use Yii;
|
||||||
|
use yii\helpers\ArrayHelper;
|
||||||
|
use yii\web\Link;
|
||||||
|
use yii\web\Linkable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||||
|
* @since 2.0
|
||||||
|
*/
|
||||||
|
trait ArrayableTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns the list of fields that should be returned by default by [[toArray()]] when no specific fields are specified.
|
||||||
|
*
|
||||||
|
* A field is a named element in the returned array by [[toArray()]].
|
||||||
|
*
|
||||||
|
* This method should return an array of field names or field definitions.
|
||||||
|
* If the former, the field name will be treated as an object property name whose value will be used
|
||||||
|
* as the field value. If the latter, the array key should be the field name while the array value should be
|
||||||
|
* the corresponding field definition which can be either an object property name or a PHP callable
|
||||||
|
* returning the corresponding field value. The signature of the callable should be:
|
||||||
|
*
|
||||||
|
* ```php
|
||||||
|
* function ($field, $model) {
|
||||||
|
* // return field value
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* For example, the following code declares four fields:
|
||||||
|
*
|
||||||
|
* - `email`: the field name is the same as the property name `email`;
|
||||||
|
* - `firstName` and `lastName`: the field names are `firstName` and `lastName`, and their
|
||||||
|
* values are obtained from the `first_name` and `last_name` properties;
|
||||||
|
* - `fullName`: the field name is `fullName`. Its value is obtained by concatenating `first_name`
|
||||||
|
* and `last_name`.
|
||||||
|
*
|
||||||
|
* ```php
|
||||||
|
* return [
|
||||||
|
* 'email',
|
||||||
|
* 'firstName' => 'first_name',
|
||||||
|
* 'lastName' => 'last_name',
|
||||||
|
* 'fullName' => function () {
|
||||||
|
* return $this->first_name . ' ' . $this->last_name;
|
||||||
|
* },
|
||||||
|
* ];
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* In this method, you may also want to return different lists of fields based on some context
|
||||||
|
* information. For example, depending on the privilege of the current application user,
|
||||||
|
* you may return different sets of visible fields or filter out some fields.
|
||||||
|
*
|
||||||
|
* The default implementation of this method returns the public object member variables.
|
||||||
|
*
|
||||||
|
* @return array the list of field names or field definitions.
|
||||||
|
* @see toArray()
|
||||||
|
*/
|
||||||
|
public function fields()
|
||||||
|
{
|
||||||
|
$fields = array_keys(Yii::getObjectVars($this));
|
||||||
|
return array_combine($fields, $fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of fields that can be expanded further and returned by [[toArray()]].
|
||||||
|
*
|
||||||
|
* This method is similar to [[fields()]] except that the list of fields returned
|
||||||
|
* by this method are not returned by default by [[toArray()]]. Only when field names
|
||||||
|
* to be expanded are explicitly specified when calling [[toArray()]], will their values
|
||||||
|
* be exported.
|
||||||
|
*
|
||||||
|
* The default implementation returns an empty array.
|
||||||
|
*
|
||||||
|
* You may override this method to return a list of expandable fields based on some context information
|
||||||
|
* (e.g. the current application user).
|
||||||
|
*
|
||||||
|
* @return array the list of expandable field names or field definitions. Please refer
|
||||||
|
* to [[fields()]] on the format of the return value.
|
||||||
|
* @see toArray()
|
||||||
|
* @see fields()
|
||||||
|
*/
|
||||||
|
public function extraFields()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the model into an array.
|
||||||
|
*
|
||||||
|
* This method will first identify which fields to be included in the resulting array by calling [[resolveFields()]].
|
||||||
|
* It will then turn the model into an array with these fields. If `$recursive` is true,
|
||||||
|
* any embedded objects will also be converted into arrays.
|
||||||
|
*
|
||||||
|
* If the model implements the [[Linkable]] interface, the resulting array will also have a `_link` element
|
||||||
|
* which refers to a list of links as specified by the interface.
|
||||||
|
*
|
||||||
|
* @param array $fields the fields being requested. If empty, all fields as specified by [[fields()]] will be returned.
|
||||||
|
* @param array $expand the additional fields being requested for exporting. Only fields declared in [[extraFields()]]
|
||||||
|
* will be considered.
|
||||||
|
* @param boolean $recursive whether to recursively return array representation of embedded objects.
|
||||||
|
* @return array the array representation of the object
|
||||||
|
*/
|
||||||
|
public function toArray(array $fields = [], array $expand = [], $recursive = true)
|
||||||
|
{
|
||||||
|
$data = [];
|
||||||
|
foreach ($this->resolveFields($fields, $expand) as $field => $definition) {
|
||||||
|
$data[$field] = is_string($definition) ? $this->$definition : call_user_func($definition, $field, $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this instanceof Linkable) {
|
||||||
|
$data['_links'] = Link::serialize($this->getLinks());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $recursive ? ArrayHelper::toArray($data) : $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines which fields can be returned by [[toArray()]].
|
||||||
|
* This method will check the requested fields against those declared in [[fields()]] and [[extraFields()]]
|
||||||
|
* to determine which fields can be returned.
|
||||||
|
* @param array $fields the fields being requested for exporting
|
||||||
|
* @param array $expand the additional fields being requested for exporting
|
||||||
|
* @return array the list of fields to be exported. The array keys are the field names, and the array values
|
||||||
|
* are the corresponding object property names or PHP callables returning the field values.
|
||||||
|
*/
|
||||||
|
protected function resolveFields(array $fields, array $expand)
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
foreach ($this->fields() as $field => $definition) {
|
||||||
|
if (is_integer($field)) {
|
||||||
|
$field = $definition;
|
||||||
|
}
|
||||||
|
if (empty($fields) || in_array($field, $fields, true)) {
|
||||||
|
$result[$field] = $definition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($expand)) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->extraFields() as $field => $definition) {
|
||||||
|
if (is_integer($field)) {
|
||||||
|
$field = $definition;
|
||||||
|
}
|
||||||
|
if (in_array($field, $expand, true)) {
|
||||||
|
$result[$field] = $definition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
@ -57,11 +57,12 @@ use yii\web\Linkable;
|
|||||||
*/
|
*/
|
||||||
class Model extends Component implements IteratorAggregate, ArrayAccess, Arrayable
|
class Model extends Component implements IteratorAggregate, ArrayAccess, Arrayable
|
||||||
{
|
{
|
||||||
|
use ArrayableTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the default scenario.
|
* The name of the default scenario.
|
||||||
*/
|
*/
|
||||||
const SCENARIO_DEFAULT = 'default';
|
const SCENARIO_DEFAULT = 'default';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @event ModelEvent an event raised at the beginning of [[validate()]]. You may set
|
* @event ModelEvent an event raised at the beginning of [[validate()]]. You may set
|
||||||
* [[ModelEvent::isValid]] to be false to stop the validation.
|
* [[ModelEvent::isValid]] to be false to stop the validation.
|
||||||
@ -829,8 +830,8 @@ class Model extends Component implements IteratorAggregate, ArrayAccess, Arrayab
|
|||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* In this method, you may also want to return different lists of fields based on some context
|
* In this method, you may also want to return different lists of fields based on some context
|
||||||
* information. For example, depending on privilege of the current application user, you may return different
|
* information. For example, depending on [[scenario]] or the privilege of the current application user,
|
||||||
* sets of visible fields.
|
* you may return different sets of visible fields or filter out some fields.
|
||||||
*
|
*
|
||||||
* The default implementation of this method returns [[attributes()]] indexed by the same attribute names.
|
* The default implementation of this method returns [[attributes()]] indexed by the same attribute names.
|
||||||
*
|
*
|
||||||
@ -843,52 +844,9 @@ class Model extends Component implements IteratorAggregate, ArrayAccess, Arrayab
|
|||||||
return array_combine($fields, $fields);
|
return array_combine($fields, $fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the list of fields that can be expanded further and returned by [[toArray()]].
|
|
||||||
*
|
|
||||||
* This method is similar to [[fields()]] except that the list of fields returned
|
|
||||||
* by this method are not returned by default by [[toArray()]]. Only when field names
|
|
||||||
* to be expanded are explicitly specified when calling [[toArray()]], will their values
|
|
||||||
* be exported.
|
|
||||||
*
|
|
||||||
* The default implementation returns an empty array.
|
|
||||||
*
|
|
||||||
* @return array the list of expandable field names or field definitions. Please refer
|
|
||||||
* to [[fields()]] on the format of the return value.
|
|
||||||
* @see toArray()
|
|
||||||
* @see fields()
|
|
||||||
*/
|
|
||||||
public function expandableFields()
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the object into an array.
|
|
||||||
* The default implementation will return [[attributes]].
|
|
||||||
* @param array $fields the fields being requested. If empty, all fields as specified by [[fields()]] will be returned.
|
|
||||||
* @param array $expand the additional fields being requested for exporting. Only fields declared in [[expandableFields()]]
|
|
||||||
* will be considered.
|
|
||||||
* @param boolean $recursive whether to recursively return array representation of embedded objects.
|
|
||||||
* @return array the array representation of the object
|
|
||||||
*/
|
|
||||||
public function toArray(array $fields = [], array $expand = [], $recursive = true)
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
foreach ($this->resolveFields($fields, $expand) as $field => $definition) {
|
|
||||||
$data[$field] = is_string($definition) ? $this->$definition : call_user_func($definition, $field, $this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this instanceof Linkable) {
|
|
||||||
$data['_links'] = Link::serialize($this->getLinks());
|
|
||||||
}
|
|
||||||
|
|
||||||
return $recursive ? ArrayHelper::toArray($data) : $data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines which fields can be returned by [[toArray()]].
|
* Determines which fields can be returned by [[toArray()]].
|
||||||
* This method will check the requested fields against those declared in [[fields()]] and [[expandableFields()]]
|
* This method will check the requested fields against those declared in [[fields()]] and [[extraFields()]]
|
||||||
* to determine which fields can be returned.
|
* to determine which fields can be returned.
|
||||||
* @param array $fields the fields being requested for exporting
|
* @param array $fields the fields being requested for exporting
|
||||||
* @param array $expand the additional fields being requested for exporting
|
* @param array $expand the additional fields being requested for exporting
|
||||||
@ -912,7 +870,7 @@ class Model extends Component implements IteratorAggregate, ArrayAccess, Arrayab
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->expandableFields() as $field => $definition) {
|
foreach ($this->extraFields() as $field => $definition) {
|
||||||
if (is_integer($field)) {
|
if (is_integer($field)) {
|
||||||
$field = $definition;
|
$field = $definition;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
namespace yii\data;
|
namespace yii\data;
|
||||||
|
|
||||||
use Yii;
|
use Yii;
|
||||||
|
use yii\base\Arrayable;
|
||||||
use yii\base\Object;
|
use yii\base\Object;
|
||||||
use yii\web\Link;
|
use yii\web\Link;
|
||||||
use yii\web\Linkable;
|
use yii\web\Linkable;
|
||||||
@ -67,7 +68,7 @@ use yii\web\Request;
|
|||||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
class Pagination extends Object implements Linkable
|
class Pagination extends Object implements Linkable, Arrayable
|
||||||
{
|
{
|
||||||
const LINK_NEXT = 'next';
|
const LINK_NEXT = 'next';
|
||||||
const LINK_PREV = 'prev';
|
const LINK_PREV = 'prev';
|
||||||
@ -315,6 +316,19 @@ class Pagination extends Object implements Linkable
|
|||||||
return $links;
|
return $links;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function toArray()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'totalCount' => $this->totalCount,
|
||||||
|
'pageCount' => $this->getPageCount(),
|
||||||
|
'currentPage' => $this->getPage(),
|
||||||
|
'perPage' => $this->getPageSize(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of the specified query parameter.
|
* Returns the value of the specified query parameter.
|
||||||
* This method returns the named parameter value from [[params]]. Null is returned if the value does not exist.
|
* This method returns the named parameter value from [[params]]. Null is returned if the value does not exist.
|
||||||
|
@ -1361,7 +1361,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
|
|||||||
*
|
*
|
||||||
* The default implementation returns the names of the relations that have been populated into this record.
|
* The default implementation returns the names of the relations that have been populated into this record.
|
||||||
*/
|
*/
|
||||||
public function expandableFields()
|
public function extraFields()
|
||||||
{
|
{
|
||||||
$fields = array_keys($this->getRelatedRecords());
|
$fields = array_keys($this->getRelatedRecords());
|
||||||
return array_combine($fields, $fields);
|
return array_combine($fields, $fields);
|
||||||
|
@ -93,7 +93,7 @@ class Action extends \yii\base\Action
|
|||||||
if (count($keys) === count($values)) {
|
if (count($keys) === count($values)) {
|
||||||
$model = $modelClass::find(array_combine($keys, $values));
|
$model = $modelClass::find(array_combine($keys, $values));
|
||||||
}
|
}
|
||||||
} else {
|
} elseif ($id !== null) {
|
||||||
$model = $modelClass::find($id);
|
$model = $modelClass::find($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
namespace yii\rest;
|
namespace yii\rest;
|
||||||
|
|
||||||
use yii\base\InvalidConfigException;
|
use yii\base\InvalidConfigException;
|
||||||
|
use yii\base\Model;
|
||||||
use yii\web\ForbiddenHttpException;
|
use yii\web\ForbiddenHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,12 +45,12 @@ class ActiveController extends Controller
|
|||||||
* @var string the scenario used for updating a model.
|
* @var string the scenario used for updating a model.
|
||||||
* @see \yii\base\Model::scenarios()
|
* @see \yii\base\Model::scenarios()
|
||||||
*/
|
*/
|
||||||
public $updateScenario = 'api-update';
|
public $updateScenario = Model::SCENARIO_DEFAULT;
|
||||||
/**
|
/**
|
||||||
* @var string the scenario used for creating a model.
|
* @var string the scenario used for creating a model.
|
||||||
* @see \yii\base\Model::scenarios()
|
* @see \yii\base\Model::scenarios()
|
||||||
*/
|
*/
|
||||||
public $createScenario = 'api-create';
|
public $createScenario = Model::SCENARIO_DEFAULT;
|
||||||
/**
|
/**
|
||||||
* @var boolean whether to use a DB transaction when creating, updating or deleting a model.
|
* @var boolean whether to use a DB transaction when creating, updating or deleting a model.
|
||||||
* This property is only useful for relational database.
|
* This property is only useful for relational database.
|
||||||
|
@ -14,7 +14,7 @@ use yii\web\IdentityInterface;
|
|||||||
use yii\web\UnauthorizedHttpException;
|
use yii\web\UnauthorizedHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AuthInterface is the interface required by classes than support user authentication.
|
* AuthInterface is the interface required by classes that support user authentication.
|
||||||
*
|
*
|
||||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
|
@ -31,10 +31,9 @@ use yii\web\VerbFilter;
|
|||||||
class Controller extends \yii\web\Controller
|
class Controller extends \yii\web\Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The name of the header parameter representing the API version number.
|
* @var string the name of the header parameter representing the API version number.
|
||||||
*/
|
*/
|
||||||
const HEADER_VERSION = 'version';
|
public $versionHeaderParam = 'version';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string|array the configuration for creating the serializer that formats the response data.
|
* @var string|array the configuration for creating the serializer that formats the response data.
|
||||||
*/
|
*/
|
||||||
@ -58,16 +57,16 @@ class Controller extends \yii\web\Controller
|
|||||||
*/
|
*/
|
||||||
public $rateLimiter = 'yii\rest\RateLimiter';
|
public $rateLimiter = 'yii\rest\RateLimiter';
|
||||||
/**
|
/**
|
||||||
* @var string the chosen API version number
|
* @var string the chosen API version number, or null if [[supportedVersions]] is empty.
|
||||||
* @see supportedVersions
|
* @see supportedVersions
|
||||||
*/
|
*/
|
||||||
public $version;
|
public $version;
|
||||||
/**
|
/**
|
||||||
* @var array list of supported API version numbers. If the current request does not specify a version
|
* @var array list of supported API version numbers. If the current request does not specify a version
|
||||||
* number, the first element will be used as the chosen version number. For this reason, you should
|
* number, the first element will be used as the [[version|chosen version number]]. For this reason, you should
|
||||||
* put the latest version number at the first.
|
* put the latest version number at the first. If this property is empty, [[version]] will not be set.
|
||||||
*/
|
*/
|
||||||
public $supportedVersions = ['1.0'];
|
public $supportedVersions = [];
|
||||||
/**
|
/**
|
||||||
* @var array list of supported response formats. The array keys are the requested content MIME types,
|
* @var array list of supported response formats. The array keys are the requested content MIME types,
|
||||||
* and the array values are the corresponding response formats. The first element will be used
|
* and the array values are the corresponding response formats. The first element will be used
|
||||||
@ -129,7 +128,7 @@ class Controller extends \yii\web\Controller
|
|||||||
*/
|
*/
|
||||||
protected function resolveFormatAndVersion()
|
protected function resolveFormatAndVersion()
|
||||||
{
|
{
|
||||||
$this->version = reset($this->supportedVersions);
|
$this->version = empty($this->supportedVersions) ? null : reset($this->supportedVersions);
|
||||||
Yii::$app->getResponse()->format = reset($this->supportedFormats);
|
Yii::$app->getResponse()->format = reset($this->supportedFormats);
|
||||||
$types = Yii::$app->getRequest()->getAcceptableContentTypes();
|
$types = Yii::$app->getRequest()->getAcceptableContentTypes();
|
||||||
if (empty($types)) {
|
if (empty($types)) {
|
||||||
@ -139,9 +138,9 @@ class Controller extends \yii\web\Controller
|
|||||||
foreach ($types as $type => $params) {
|
foreach ($types as $type => $params) {
|
||||||
if (isset($this->supportedFormats[$type])) {
|
if (isset($this->supportedFormats[$type])) {
|
||||||
Yii::$app->getResponse()->format = $this->supportedFormats[$type];
|
Yii::$app->getResponse()->format = $this->supportedFormats[$type];
|
||||||
if (isset($params[self::HEADER_VERSION])) {
|
if (isset($params[$this->versionHeaderParam])) {
|
||||||
if (in_array($params[self::HEADER_VERSION], $this->supportedVersions, true)) {
|
if (in_array($params[$this->versionHeaderParam], $this->supportedVersions, true)) {
|
||||||
$this->version = $params[self::HEADER_VERSION];
|
$this->version = $params[$this->versionHeaderParam];
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedMediaTypeHttpException('You are requesting an invalid version number.');
|
throw new UnsupportedMediaTypeHttpException('You are requesting an invalid version number.');
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
namespace yii\rest;
|
namespace yii\rest;
|
||||||
|
|
||||||
use Yii;
|
use Yii;
|
||||||
|
use yii\base\Model;
|
||||||
use yii\db\ActiveRecord;
|
use yii\db\ActiveRecord;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,7 +22,7 @@ class CreateAction extends Action
|
|||||||
/**
|
/**
|
||||||
* @var string the scenario to be assigned to the new model before it is validated and saved.
|
* @var string the scenario to be assigned to the new model before it is validated and saved.
|
||||||
*/
|
*/
|
||||||
public $scenario = 'api-create';
|
public $scenario = Model::SCENARIO_DEFAULT;
|
||||||
/**
|
/**
|
||||||
* @var boolean whether to start a DB transaction when saving the model.
|
* @var boolean whether to start a DB transaction when saving the model.
|
||||||
*/
|
*/
|
||||||
|
@ -13,31 +13,93 @@ use yii\base\Model;
|
|||||||
use yii\data\DataProviderInterface;
|
use yii\data\DataProviderInterface;
|
||||||
use yii\data\Pagination;
|
use yii\data\Pagination;
|
||||||
use yii\helpers\ArrayHelper;
|
use yii\helpers\ArrayHelper;
|
||||||
|
use yii\web\Link;
|
||||||
use yii\web\Request;
|
use yii\web\Request;
|
||||||
use yii\web\Response;
|
use yii\web\Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Serializer converts resource objects and collections into array representation.
|
||||||
|
*
|
||||||
|
* Serializer is mainly used by REST controllers to convert different objects into array representation
|
||||||
|
* so that they can be further turned into different formats, such as JSON, XML, by response formatters.
|
||||||
|
*
|
||||||
|
* The default implementation handles resources as [[Model]] objects and collections as objects
|
||||||
|
* implementing [[DataProviderInterface]]. You may override [[serialize()]] to handle more types.
|
||||||
*
|
*
|
||||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
class Serializer extends Component
|
class Serializer extends Component
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var string the name of the query parameter containing the information about which fields should be returned
|
||||||
|
* for a [[Model]] object. If the parameter is not provided or empty, the default set of fields as defined
|
||||||
|
* by [[Model::fields()]] will be returned.
|
||||||
|
*/
|
||||||
public $fieldsParam = 'fields';
|
public $fieldsParam = 'fields';
|
||||||
|
/**
|
||||||
|
* @var string the name of the query parameter containing the information about which fields should be returned
|
||||||
|
* in addition to those listed in [[fieldsParam]] for a resource object.
|
||||||
|
*/
|
||||||
public $expandParam = 'expand';
|
public $expandParam = 'expand';
|
||||||
|
/**
|
||||||
|
* @var string the name of the HTTP header containing the information about total number of data items.
|
||||||
|
* This is used when serving a resource collection with pagination.
|
||||||
|
*/
|
||||||
public $totalCountHeader = 'X-Pagination-Total-Count';
|
public $totalCountHeader = 'X-Pagination-Total-Count';
|
||||||
|
/**
|
||||||
|
* @var string the name of the HTTP header containing the information about total number of pages of data.
|
||||||
|
* This is used when serving a resource collection with pagination.
|
||||||
|
*/
|
||||||
public $pageCountHeader = 'X-Pagination-Page-Count';
|
public $pageCountHeader = 'X-Pagination-Page-Count';
|
||||||
|
/**
|
||||||
|
* @var string the name of the HTTP header containing the information about the current page number (1-based).
|
||||||
|
* This is used when serving a resource collection with pagination.
|
||||||
|
*/
|
||||||
public $currentPageHeader = 'X-Pagination-Current-Page';
|
public $currentPageHeader = 'X-Pagination-Current-Page';
|
||||||
|
/**
|
||||||
|
* @var string the name of the HTTP header containing the information about the number of data items in each page.
|
||||||
|
* This is used when serving a resource collection with pagination.
|
||||||
|
*/
|
||||||
public $perPageHeader = 'X-Pagination-Per-Page';
|
public $perPageHeader = 'X-Pagination-Per-Page';
|
||||||
/**
|
/**
|
||||||
* @var Request
|
* @var string the name of the envelope (e.g. `items`) for returning the resource objects in a collection.
|
||||||
|
* This is used when serving a resource collection. When this is set and pagination is enabled, the serializer
|
||||||
|
* will return a collection in the following format:
|
||||||
|
*
|
||||||
|
* ```php
|
||||||
|
* [
|
||||||
|
* 'items' => [...], // assuming collectionEnvelope is "items"
|
||||||
|
* '_links' => { // pagination links as returned by Pagination::getLinks()
|
||||||
|
* 'self' => '...',
|
||||||
|
* 'next' => '...',
|
||||||
|
* 'last' => '...',
|
||||||
|
* },
|
||||||
|
* '_meta' => { // meta information as returned by Pagination::toArray()
|
||||||
|
* 'totalCount' => 100,
|
||||||
|
* 'pageCount' => 5,
|
||||||
|
* 'currentPage' => 1,
|
||||||
|
* 'perPage' => 20,
|
||||||
|
* },
|
||||||
|
* ]
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If this property is not set, the resource arrays will be directly returned without using envelope.
|
||||||
|
* The pagination information as shown in `_links` and `_meta` can be accessed from the response HTTP headers.
|
||||||
|
*/
|
||||||
|
public $collectionEnvelope;
|
||||||
|
/**
|
||||||
|
* @var Request the current request. If not set, the `request` application component will be used.
|
||||||
*/
|
*/
|
||||||
public $request;
|
public $request;
|
||||||
/**
|
/**
|
||||||
* @var Response
|
* @var Response the response to be sent. If not set, the `response` application component will be used.
|
||||||
*/
|
*/
|
||||||
public $response;
|
public $response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
if ($this->request === null) {
|
if ($this->request === null) {
|
||||||
@ -48,6 +110,15 @@ class Serializer extends Component
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes the given data into a format that can be easily turned into other formats.
|
||||||
|
* This method mainly converts the objects of recognized types into array representation.
|
||||||
|
* It will not do conversion for unknown object types or non-object data.
|
||||||
|
* The default implementation will handle [[Model]] and [[DataProviderInterface]].
|
||||||
|
* You may override this method to support more object types.
|
||||||
|
* @param mixed $data the data to be serialized.
|
||||||
|
* @return mixed the converted data.
|
||||||
|
*/
|
||||||
public function serialize($data)
|
public function serialize($data)
|
||||||
{
|
{
|
||||||
if ($data instanceof Model) {
|
if ($data instanceof Model) {
|
||||||
@ -59,6 +130,13 @@ class Serializer extends Component
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array the names of the requested fields. The first element is an array
|
||||||
|
* representing the list of default fields requested, while the second element is
|
||||||
|
* an array of the extra fields requested in addition to the default fields.
|
||||||
|
* @see Model::fields()
|
||||||
|
* @see Model::extraFields()
|
||||||
|
*/
|
||||||
protected function getRequestedFields()
|
protected function getRequestedFields()
|
||||||
{
|
{
|
||||||
$fields = $this->request->get($this->fieldsParam);
|
$fields = $this->request->get($this->fieldsParam);
|
||||||
@ -70,12 +148,13 @@ class Serializer extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Serializes a data provider.
|
||||||
* @param DataProviderInterface $dataProvider
|
* @param DataProviderInterface $dataProvider
|
||||||
* @return array
|
* @return array the array representation of the data provider.
|
||||||
*/
|
*/
|
||||||
protected function serializeDataProvider($dataProvider)
|
protected function serializeDataProvider($dataProvider)
|
||||||
{
|
{
|
||||||
$models = $dataProvider->getModels();
|
$models = $this->serializeModels($dataProvider->getModels());
|
||||||
|
|
||||||
if (($pagination = $dataProvider->getPagination()) !== false) {
|
if (($pagination = $dataProvider->getPagination()) !== false) {
|
||||||
$this->addPaginationHeaders($pagination);
|
$this->addPaginationHeaders($pagination);
|
||||||
@ -83,12 +162,22 @@ class Serializer extends Component
|
|||||||
|
|
||||||
if ($this->request->getIsHead()) {
|
if ($this->request->getIsHead()) {
|
||||||
return null;
|
return null;
|
||||||
|
} elseif ($this->collectionEnvelope === null) {
|
||||||
|
return $models;
|
||||||
} else {
|
} else {
|
||||||
return $this->serializeModels($models);
|
$result = [
|
||||||
|
$this->collectionEnvelope => $models,
|
||||||
|
];
|
||||||
|
if ($pagination !== false) {
|
||||||
|
$result['_links'] = Link::serialize($pagination->getLinks());
|
||||||
|
$result['_meta'] = $pagination->toArray();
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Adds HTTP headers about the pagination to the response.
|
||||||
* @param Pagination $pagination
|
* @param Pagination $pagination
|
||||||
*/
|
*/
|
||||||
protected function addPaginationHeaders($pagination)
|
protected function addPaginationHeaders($pagination)
|
||||||
@ -107,8 +196,9 @@ class Serializer extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Serializes a model object.
|
||||||
* @param Model $model
|
* @param Model $model
|
||||||
* @return array
|
* @return array the array representation of the model
|
||||||
*/
|
*/
|
||||||
protected function serializeModel($model)
|
protected function serializeModel($model)
|
||||||
{
|
{
|
||||||
@ -121,8 +211,9 @@ class Serializer extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Serializes the validation errors in a model.
|
||||||
* @param Model $model
|
* @param Model $model
|
||||||
* @return array
|
* @return array the array representation of the errors
|
||||||
*/
|
*/
|
||||||
protected function serializeModelErrors($model)
|
protected function serializeModelErrors($model)
|
||||||
{
|
{
|
||||||
@ -137,6 +228,11 @@ class Serializer extends Component
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes a set of models.
|
||||||
|
* @param array $models
|
||||||
|
* @return array the array representation of the models
|
||||||
|
*/
|
||||||
protected function serializeModels(array $models)
|
protected function serializeModels(array $models)
|
||||||
{
|
{
|
||||||
list ($fields, $expand) = $this->getRequestedFields();
|
list ($fields, $expand) = $this->getRequestedFields();
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
namespace yii\rest;
|
namespace yii\rest;
|
||||||
|
|
||||||
use Yii;
|
use Yii;
|
||||||
|
use yii\base\Model;
|
||||||
use yii\db\ActiveRecord;
|
use yii\db\ActiveRecord;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,7 +22,7 @@ class UpdateAction extends Action
|
|||||||
/**
|
/**
|
||||||
* @var string the scenario to be assigned to the model before it is validated and updated.
|
* @var string the scenario to be assigned to the model before it is validated and updated.
|
||||||
*/
|
*/
|
||||||
public $scenario = 'api-update';
|
public $scenario = Model::SCENARIO_DEFAULT;
|
||||||
/**
|
/**
|
||||||
* @var boolean whether to start a DB transaction when saving the model.
|
* @var boolean whether to start a DB transaction when saving the model.
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user