Browse Source

docs for REST moved to "yiisoft/yii2-rest"

tags/3.0.0-alpha1
Paul Klimov 7 years ago
parent
commit
39e9ba74bc
  1. 14
      docs/guide-es/README.md
  2. 127
      docs/guide-es/rest-authentication.md
  3. 156
      docs/guide-es/rest-controllers.md
  4. 94
      docs/guide-es/rest-error-handling.md
  5. 203
      docs/guide-es/rest-quick-start.md
  6. 44
      docs/guide-es/rest-rate-limiting.md
  7. 190
      docs/guide-es/rest-resources.md
  8. 157
      docs/guide-es/rest-response-formatting.md
  9. 92
      docs/guide-es/rest-routing.md
  10. 111
      docs/guide-es/rest-versioning.md
  11. 14
      docs/guide-fr/README.md
  12. 14
      docs/guide-pl/README.md
  13. 90
      docs/guide-pl/rest-error-handling.md
  14. 37
      docs/guide-pl/rest-rate-limiting.md
  15. 90
      docs/guide-pl/rest-routing.md
  16. 112
      docs/guide-pl/rest-versioning.md
  17. 14
      docs/guide-pt-BR/README.md
  18. 104
      docs/guide-pt-BR/rest-authentication.md
  19. 133
      docs/guide-pt-BR/rest-controllers.md
  20. 85
      docs/guide-pt-BR/rest-error-handling.md
  21. 193
      docs/guide-pt-BR/rest-quick-start.md
  22. 38
      docs/guide-pt-BR/rest-rate-limiting.md
  23. 192
      docs/guide-pt-BR/rest-resources.md
  24. 139
      docs/guide-pt-BR/rest-response-formatting.md
  25. 85
      docs/guide-pt-BR/rest-routing.md
  26. 94
      docs/guide-pt-BR/rest-versioning.md
  27. 14
      docs/guide-ru/README.md
  28. 126
      docs/guide-ru/rest-authentication.md
  29. 157
      docs/guide-ru/rest-controllers.md
  30. 92
      docs/guide-ru/rest-error-handling.md
  31. 191
      docs/guide-ru/rest-quick-start.md
  32. 69
      docs/guide-ru/rest-rate-limiting.md
  33. 208
      docs/guide-ru/rest-resources.md
  34. 185
      docs/guide-ru/rest-response-formatting.md
  35. 92
      docs/guide-ru/rest-routing.md
  36. 112
      docs/guide-ru/rest-versioning.md
  37. 14
      docs/guide-uk/README.md
  38. 66
      docs/guide-uk/rest-rate-limiting.md
  39. 14
      docs/guide/README.md
  40. 127
      docs/guide/rest-authentication.md
  41. 191
      docs/guide/rest-controllers.md
  42. 94
      docs/guide/rest-error-handling.md
  43. 209
      docs/guide/rest-quick-start.md
  44. 66
      docs/guide/rest-rate-limiting.md
  45. 261
      docs/guide/rest-resources.md
  46. 187
      docs/guide/rest-response-formatting.md
  47. 110
      docs/guide/rest-routing.md
  48. 111
      docs/guide/rest-versioning.md
  49. 10
      docs/guide/structure-extensions.md

14
docs/guide-es/README.md

@ -130,20 +130,6 @@ Caché
* [Caché HTTP](caching-http.md)
Servicios Web RESTful
---------------------
* [Guía breve](rest-quick-start.md)
* [Recursos (Resources)](rest-resources.md)
* [Controladores](rest-controllers.md)
* [Gestión de rutas](rest-routing.md)
* [Formateo de respuestas](rest-response-formatting.md)
* [Autenticación](rest-authentication.md)
* [Límite de Rango](rest-rate-limiting.md)
* [Gestión de versiones](rest-versioning.md)
* [Gestión de errores](rest-error-handling.md)
Herramientas de Desarrollo
--------------------------

127
docs/guide-es/rest-authentication.md

@ -1,127 +0,0 @@
Autenticación
=============
A diferencia de las aplicaciones Web, las API RESTful son usualmente sin estado (stateless), lo que permite que las sesiones o las cookies
no sean usadas. Por lo tanto, cada petición debe llevar alguna suerte de credenciales de autenticación,
porque la autenticación del usuario no puede ser mantenida por las sesiones o las cookies. Una práctica común
es enviar una pieza (token) secreta de acceso con cada petición para autenticar al usuario. Dado que una pieza de autenticación
puede ser usada para identificar y autenticar solamente a un usuario, **la API de peticiones tiene que ser siempre enviado
vía HTTPS para prevenir ataques tipo "man-in-the-middle" (MitM) **.
Hay muchas maneras de enviar una token (pieza) de acceso:
* [Autenticación Básica HTTP](https://es.wikipedia.org/wiki/Autenticaci%C3%B3n_de_acceso_b%C3%A1sica): la pieza de acceso
es enviada como nombre de usuario. Esto sólo debe de ser usado cuando la pieza de acceso puede ser guardada
de forma segura en la parte del API del consumidor. Por ejemplo, el API del consumidor es un programa ejecutándose en un servidor.
* Parámetro de la consulta: la pieza de acceso es enviada como un parámetro de la consulta en la URL de la API, p.e.,
`https://example.com/users?access-token=xxxxxxxx`. Debido que muchos servidores dejan los parámetros de consulta en los logs del servidor,
esta aproximación suele ser usada principalmente para servir peticiones `JSONP`
que no usen las cabeceras HTTP para enviar piezas de acceso.
* [OAuth 2](http://oauth.net/2/): la pieza de acceso es obtenida por el consumidor por medio de una autorización del servidor
y enviada al API del servidor según el protocolo
OAuth 2 [tokens HTTP del portador](http://tools.ietf.org/html/rfc6750).
Yii soporta todos los métodos anteriores de autenticación. Puedes crear nuevos métodos de autenticación de una forma fácil.
Para activar la autenticación para tus APIs, sigue los pasos siguientes:
1. Configura el componente `user` de la aplicación:
- Define la propiedad [[yii\web\User::enableSession|enableSession]] como `false`.
- Define la propiedad [[yii\web\User::loginUrl|loginUrl]] como `null` para mostrar un error HTTP 403 en vez de redireccionar a la pantalla de login.
2. Especifica cuál método de autenticación planeas usar configurando el comportamiento (behavior) `authenticator` en tus
clases de controladores REST.
3. Implementa [[yii\web\IdentityInterface::findIdentityByAccessToken()]] en tu [[yii\web\User::identityClass|clase de identidad de usuarios]].
El paso 1 no es necesario pero sí recomendable para las APIs RESTful, pues son sin estado (stateless).
Cuando [[yii\web\User::enableSession|enableSession]] es `false`, el estado de autenticación del usuario puede NO persistir entre peticiones usando sesiones.
Si embargo, la autenticación será realizada para cada petición, lo que se consigue en los pasos 2 y 3.
> Tip:Puedes configurar [[yii\web\User::enableSession|enableSession]] del componente de la aplicación `user` en la configuración
> de las aplicaciones si estás desarrollando APIs RESTful en términos de un aplicación. Si desarrollas un módulo de las APIs RESTful,
> puedes poner la siguiente línea en el método del módulo `init()`, tal y como sigue:
>
> ```php
> public function init()
> {
> parent::init();
> \Yii::$app->user->enableSession = false;
> }
> ```
Por ejemplo, para usar HTTP Basic Auth, puedes configurar el comportamiento (behavior) `authenticator` como sigue,
```php
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpBasicAuth::class,
];
return $behaviors;
}
```
Si quieres implementar los tres métodos de autenticación explicados antes, puedes usar `CompositeAuth` de la siguiente manera,
```php
use yii\filters\auth\CompositeAuth;
use yii\filters\auth\HttpBasicAuth;
use yii\filters\auth\HttpBearerAuth;
use yii\filters\auth\QueryParamAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => CompositeAuth::class,
'authMethods' => [
HttpBasicAuth::class,
HttpBearerAuth::class,
QueryParamAuth::class,
],
];
return $behaviors;
}
```
Cada elemento en `authMethods` debe de ser el nombre de una clase de método de autenticación o un array de configuración.
La implementación de `findIdentityByAccessToken()` es específico de la aplicación. Por ejemplo, en escenarios simples
cuando cada usuario sólo puede tener un token de acceso, puedes almacenar este token en la columna `access_token`
en la tabla de usuario. El método debe de ser inmediatamente implementado en la clase `User` como sigue,
```php
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
class User extends ActiveRecord implements IdentityInterface
{
public static function findIdentityByAccessToken($token, $type = null)
{
return static::findOne(['access_token' => $token]);
}
}
```
Después que la autenticación es activada, tal y como se describe arriba, para cada petición de la API, el controlador solicitado
puede intentar autenticar al usuario en su evento `beforeAction()`.
Si la autenticación tiene éxito, el controlador realizará otras comprobaciones (como son límite del ratio, autorización)
y entonces ejecutar la acción. La identidad del usuario autenticado puede ser recuperada via `Yii::$app->user->identity`.
Si la autenticación falla, una respuesta con estado HTTP 401 será devuelta junto con otras cabeceras apropiadas
(tal como la cabecera para autenticación básica HTTP `WWW-Authenticate`).
## Autorización <span id="authorization"></span>
Después de que un usuario se ha autenticado, probablementer querrás comprobar si él o ella tiene los permisos para realizar
la acción solicitada. Este proceso es llamado *autorización (authorization)* y está cubierto en detalle
en la [Sección de Autorización](security-authorization.md).
Si tus controladores extienden de [[yii\rest\ActiveController]], puedes sobreescribir
el método [[yii\rest\ActiveController::checkAccess()|checkAccess()]] para realizar la comprobación de la autorización.
El método será llamado por las acciones contenidas en [[yii\rest\ActiveController]].

156
docs/guide-es/rest-controllers.md

@ -1,156 +0,0 @@
Controladores
=============
Después de crear las clases de recursos y especificar cómo debe ser el formato de datos de recursos, el siguiente paso
es crear acciones del controlador para exponer los recursos a los usuarios finales a través de las APIs RESTful.
Yii ofrece dos clases controlador base para simplificar tu trabajo de crear acciones REST:
[[yii\rest\Controller]] y [[yii\rest\ActiveController]]. La diferencia entre estos dos controladores
es que este último proporciona un conjunto predeterminado de acciones que están específicamente diseñado para trabajar con
los recursos representados como [Active Record](db-active-record.md). Así que si estás utilizando [Active Record](db-active-record.md)
y te sientes cómodo con las acciones integradas provistas, podrías considerar extender tus controladores
de [[yii\rest\ActiveController]], lo que te permitirá crear potentes APIs RESTful con un mínimo de código.
Ambos [[yii\rest\Controller]] y [[yii\rest\ActiveController]] proporcionan las siguientes características,
algunas de las cuales se describen en detalle en las siguientes secciones:
* Método de Validación HTTP;
* [Negociación de contenido y formato de datos](rest-response-formatting.md);
* [Autenticación](rest-authentication.md);
* [Límite de Rango](rest-rate-limiting.md).
[[yii\rest\ActiveController]] además provee de las siguientes características:
* Un conjunto de acciones comunes necesarias: `index`, `view`, `create`, `update`, `delete`, `options`;
* La autorización del usuario de acuerdo a la acción y recurso solicitado.
## Creando Clases de Controlador <span id="creating-controller"></span>
Al crear una nueva clase de controlador, una convención para nombrar la clase del controlador es utilizar
el nombre del tipo de recurso en singular. Por ejemplo, para servir información de usuario,
el controlador puede ser nombrado como `UserController`.
Crear una nueva acción es similar a crear una acción para una aplicación Web. La única diferencia
es que en lugar de renderizar el resultado utilizando una vista llamando al método `render()`, para las acciones REST
regresas directamente los datos. El [[yii\rest\Controller::serializer|serializer]] y el
[[yii\web\Response|response object]] se encargarán de la conversión de los datos originales
al formato solicitado. Por ejemplo,
```php
public function actionView($id)
{
return User::findOne($id);
}
```
## Filtros <span id="filters"></span>
La mayoría de las características API REST son proporcionadas por [[yii\rest\Controller]] son implementadas en los términos de [filtros](structure-filters.md).
En particular, los siguientes filtros se ejecutarán en el orden en que aparecen:
* [[yii\filters\ContentNegotiator|contentNegotiator]]: soporta la negociación de contenido, que se explica en
la sección [Formateo de respuestas](rest-response-formatting.md);
* [[yii\filters\VerbFilter|verbFilter]]: soporta métodos de validación HTTP;
* [[yii\filters\auth\AuthMethod|authenticator]]: soporta la autenticación de usuarios, que se explica en
la sección [Autenticación](rest-authentication.md);
* [[yii\filters\RateLimiter|rateLimiter]]: soporta la limitación de rango, que se explica en
la sección [Límite de Rango](rest-rate-limiting.md).
Estos filtros se declaran nombrándolos en el método [[yii\rest\Controller::behaviors()|behaviors()]].
Puede sobrescribir este método para configurar filtros individuales, desactivar algunos de ellos, o añadir los tuyos.
Por ejemplo, si sólo deseas utilizar la autenticación básica HTTP, puede escribir el siguiente código:
```php
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpBasicAuth::class,
];
return $behaviors;
}
```
## Extendiendo `ActiveController` <span id="extending-active-controller"></span>
Si tu clase controlador extiende de [[yii\rest\ActiveController]], debe establecer
su propiedad [[yii\rest\ActiveController::modelClass|modelClass]] con el nombre de la clase del recurso
que planeas servir a través de este controlador. La clase debe extender de [[yii\db\ActiveRecord]].
### Personalizando Acciones <span id="customizing-actions"></span>
Por defecto, [[yii\rest\ActiveController]] provee de las siguientes acciones:
* [[yii\rest\IndexAction|index]]: listar recursos página por página;
* [[yii\rest\ViewAction|view]]: devolver el detalle de un recurso específico;
* [[yii\rest\CreateAction|create]]: crear un nuevo recurso;
* [[yii\rest\UpdateAction|update]]: actualizar un recurso existente;
* [[yii\rest\DeleteAction|delete]]: eliminar un recurso específico;
* [[yii\rest\OptionsAction|options]]: devolver los métodos HTTP soportados.
Todas esta acciones se declaran a través de método [[yii\rest\ActiveController::actions()|actions()]].
Puedes configurar estas acciones o desactivar alguna de ellas sobrescribiendo el método `actions()`, como se muestra a continuación,
```php
public function actions()
{
$actions = parent::actions();
// disable the "delete" and "create" actions
unset($actions['delete'], $actions['create']);
// customize the data provider preparation with the "prepareDataProvider()" method
$actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider'];
return $actions;
}
public function prepareDataProvider()
{
// prepare and return a data provider for the "index" action
}
```
Por favor, consulta las referencias de clases de acciones individuales para aprender las opciones de configuración disponibles para cada una.
### Realizando Comprobación de Acceso <span id="performing-access-check"></span>
Al exponer los recursos a través de RESTful APIs, a menudo es necesario comprobar si el usuario actual tiene permiso
para acceder y manipular el/los recurso solicitado/s. Con [[yii\rest\ActiveController]], esto puede lograrse
sobrescribiendo el método [[yii\rest\ActiveController::checkAccess()|checkAccess()]] como a continuación,
```php
/**
* Checks the privilege of the current user.
*
* This method should be overridden to check whether the current user has the privilege
* to run the specified action against the specified data model.
* If the user does not have access, a [[ForbiddenHttpException]] should be thrown.
*
* @param string $action the ID of the action to be executed
* @param \yii\base\Model $model the model to be accessed. If `null`, it means no specific model is being accessed.
* @param array $params additional parameters
* @throws ForbiddenHttpException if the user does not have access
*/
public function checkAccess($action, $model = null, $params = [])
{
// check if the user can access $action and $model
// throw ForbiddenHttpException if access should be denied
if ($action === 'update' || $action === 'delete') {
if ($model->author_id !== \Yii::$app->user->id)
throw new \yii\web\ForbiddenHttpException(sprintf('You can only %s articles that you\'ve created.', $action));
}
}
```
El método `checkAccess()` será llamado por defecto en las acciones predeterminadas de [[yii\rest\ActiveController]]. Si creas
nuevas acciones y también deseas llevar a cabo la comprobación de acceso, debe llamar a este método de forma explícita en las nuevas acciones.
> Tip: Puedes implementar `checkAccess()` mediante el uso del [Componente Role-Based Access Control (RBAC)](security-authorization.md).

94
docs/guide-es/rest-error-handling.md

@ -1,94 +0,0 @@
Manejo de errores
=================
Cuando se maneja una petición de API RESTful, si ocurre un error en la petición del usuario o si algo inesperado
ocurre en el servidor, simplemente puedes lanzar una excepción para notificar al usuario que algo erróneo ocurrió.
Si puedes identificar la causa del error (p.e., el recurso solicitado no existe), debes considerar lanzar una excepción
con el código HTTP de estado apropiado (p.e., [[yii\web\NotFoundHttpException]] representa un código de estado 404).
Yii enviará la respuesta a continuación con el correspondiente código de estado HTTP y el texto. Yii puede incluir también
la representación serializada de la excepción en el cuerpo de la respuesta.
Por ejemplo:
```
HTTP/1.1 404 Not Found
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
```
La siguiente lista sumariza los códigos de estado HTTP que son usados por el framework REST:
* `200`: OK. Todo ha funcionado como se esperaba.
* `201`: El recurso ha creado con éxito en respuesta a la petición `POST`. La cabecera de situación `Location`
contiene la URL apuntando al nuevo recurso creado.
* `204`: La petición ha sido manejada con éxito y el cuerpo de la respuesta no tiene contenido (como una petición `DELETE`).
* `304`: El recurso no ha sido modificado. Puede usar la versión en caché.
* `400`: Petición errónea. Esto puede estar causado por varias acciones de el usuario, como proveer un JSON no válido
en el cuerpo de la petición, proveyendo parámetros de acción no válidos, etc.
* `401`: Autenticación fallida.
* `403`: El usuario autenticado no tiene permitido acceder a la API final.
* `404`: El recurso pedido no existe.
* `405`: Método no permitido. Por favor comprueba la cabecera `Allow` por los métodos HTTP permitidos.
* `415`: Tipo de medio no soportado. El tipo de contenido pedido o el número de versión no es válido.
* `422`: La validación de datos ha fallado (en respuesta a una petición `POST` , por ejemplo). Por favor, comprueba en el cuerpo de la respuesta el mensaje detallado.
* `429`: Demasiadas peticiones. La petición ha sido rechazada debido a un limitación de rango.
* `500`: Error interno del servidor. Esto puede estar causado por errores internos del programa.
## Personalizar la Respuesta al Error <span id="customizing-error-response"></span>
A veces puedes querer personalizar el formato de la respuesta del error por defecto . Por ejemplo, en lugar de depender
del uso de diferentes estados HTTP para indicar los diferentes errores, puedes querer usar siempre el estado HTTP 200
y encapsular el código de estado HTTP real como parte de una estructura JSON en la respuesta, como se muestra a continuación,
```
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"success": false,
"data": {
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
}
```
Para lograrlo, puedes responder al evento `beforeSend` del componente `response` en la configuración de la aplicación:
```php
return [
// ...
'components' => [
'response' => [
'class' => 'yii\web\Response',
'on beforeSend' => function ($event) {
$response = $event->sender;
if ($response->data !== null && Yii::$app->request->get('suppress_response_code')) {
$response->data = [
'success' => $response->isSuccessful,
'data' => $response->data,
];
$response->statusCode = 200;
}
},
],
],
];
```
El anterior código reformateará la respuesta (sea exitosa o fallida) como se explicó cuando
`suppress_response_code` es pasado como un parámetro `GET`.

203
docs/guide-es/rest-quick-start.md

@ -1,203 +0,0 @@
Guía Breve
==========
Yii ofrece todo un conjunto de herramientas para simplificar la tarea de implementar un
servicio web APIs RESTful.
En particular, Yii soporta las siguientes características sobre APIs RESTful;
* Prototipado rápido con soporte para APIs comunes para [Active Record](db-active-record.md);
* Formato de respuesta de negocio (soporta JSON y XML por defecto);
* Personalización de objetos serializados con soporte para campos de salida seleccionables;
* Formateo apropiado de colecciones de datos y validación de errores;
* Soporte para [HATEOAS](http://en.wikipedia.org/wiki/HATEOAS);
* Eficiente enrutamiento con una adecuada comprobación del verbo(verb) HTTP;
* Incorporado soporte para las `OPTIONS` y `HEAD` verbos;
* Autenticación y autorización;
* Cacheo de datos y cacheo HTTP;
* Limitación de rango;
A continuación, utilizamos un ejemplo para ilustrar como se puede construir un conjunto de APIs RESTful con un esfuerzo mínimo de codificación.
Supongamos que deseas exponer los datos de los usuarios vía APIs RESTful. Los datos de usuario son almacenados en la tabla DB `user`,
y ya tienes creado la clase [[yii\db\ActiveRecord|ActiveRecord]] `app\models\User` para acceder a los datos del usuario.
## Creando un controlador <span id="creating-controller"></span>
Primero, crea una clase controladora `app\controllers\UserController` como la siguiente,
```php
namespace app\controllers;
use yii\rest\ActiveController;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
}
```
La clase controladora extiende de [[yii\rest\ActiveController]]. Especificado por [[yii\rest\ActiveController::modelClass|modelClass]]
como `app\models\User`, el controlador sabe que modelo puede ser usado para recoger y manipular sus datos.
## Configurando las reglas de las URL <span id="configuring-url-rules"></span>
A continuación, modifica la configuración del componente `urlManager` en la configuración de tu aplicación:
```php
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
],
]
```
La configuración anterior principalmente añade una regla URL para el controlador `user` de manera
que los datos de user pueden ser accedidos y manipulados con URLs amigables y verbos HTTP significativos.
## Habilitando entradas JSON <span id="enabling-json-input"></span>
Para permitir que la API acepte datos de entrada con formato JSON, configura la propiedad [[yii\web\Request::$parsers|parsers]]
del componente de aplicación `request` para usar [[yii\web\JsonParser]] para entradas JSON:
```php
'request' => [
'parsers' => [
'application/json' => 'yii\web\JsonParser',
]
]
```
> Tip: La configuración anterior es opcional. Sin la configuración anterior, la API sólo reconocería
`application/x-www-form-urlencoded` y `multipart/form-data` como formatos de entrada.
## Probándolo <span id="trying-it-out"></span>
Con la mínima cantidad de esfuerzo, tienes ya finalizado tu tarea de crear las APIs RESTful
para acceder a los datos de user. Las APIs que tienes creado incluyen:
* `GET /users`: una lista de todos los usuarios página por página;
* `HEAD /users`: muestra la información general de la lista de usuarios;
* `POST /users`: crea un nuevo usuario;
* `GET /users/123`: devuelve los detalles del usuario 123;
* `HEAD /users/123`: muestra la información general del usuario 123;
* `PATCH /users/123` y `PUT /users/123`: actualiza el usuario 123;
* `DELETE /users/123`: elimina el usuario 123;
* `OPTIONS /users`: muestra los verbos compatibles respecto al punto final `/users`;
* `OPTIONS /users/123`: muestra los verbos compatibles respecto al punto final `/users/123`.
> Info: Yii automáticamente pluraliza los nombres de los controladores para usarlo en los puntos finales.
> Puedes configurar esto usando la propiedad [[yii\rest\UrlRule::$pluralize]].
Puedes acceder a tus APIs con el comando `curl` de la siguiente manera,
```
$ curl -i -H "Accept:application/json" "http://localhost/users"
HTTP/1.1 200 OK
...
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
[
{
"id": 1,
...
},
{
"id": 2,
...
},
...
]
```
Intenta cambiar el tipo de contenido aceptado para ser `application/xml`, y verá que el resultado
se devuelve en formato XML:
```
$ curl -i -H "Accept:application/xml" "http://localhost/users"
HTTP/1.1 200 OK
...
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/xml
<?xml version="1.0" encoding="UTF-8"?>
<response>
<item>
<id>1</id>
...
</item>
<item>
<id>2</id>
...
</item>
...
</response>
```
El siguiente comando creará un nuevo usuario mediante el envío de una petición POST con los datos del usuario en formato JSON:
```
$ curl -i -H "Accept:application/json" -H "Content-Type:application/json" -XPOST "http://localhost/users" -d '{"username": "example", "email": "user@example.com"}'
HTTP/1.1 201 Created
...
Location: http://localhost/users/1
Content-Length: 99
Content-Type: application/json; charset=UTF-8
{"id":1,"username":"example","email":"user@example.com","created_at":1414674789,"updated_at":1414674789}
```
> Tip: También puedes acceder a tus APIs a través del navegador web introduciendo la URL `http://localhost/users`.
Sin embargo, es posible que necesites algunos plugins para el navegador para enviar cabeceras especificas en la petición.
Como se puede ver, en las cabeceras de la respuesta, hay información sobre la cuenta total, número de páginas, etc.
También hay enlaces que permiten navegar por otras páginas de datos. Por ejemplo, `http://localhost/users?page=2`
le daría la página siguiente de los datos de usuario.
Utilizando los parámetros `fields` y `expand`, puedes también especificar que campos deberían ser incluidos en el resultado.
Por ejemplo, la URL `http://localhost/users?fields=id,email` sólo devolverá los campos `id` y `email`.
> Info: Puedes haber notado que el resultado de `http://localhost/users` incluye algunos campos sensibles,
> tal como `password_hash`, `auth_key`. Seguramente no quieras que éstos aparecieran en el resultado de tu API.
> Puedes y deberías filtrar estos campos como se describe en la sección [Response Formatting](rest-response-formatting.md).
## Resumen <span id="summary"></span>
Utilizando el framework Yii API RESTful, implementa un punto final API en términos de una acción de un controlador, y utiliza
un controlador para organizar las acciones que implementan los puntos finales para un sólo tipo de recurso.
Los recursos son representados como modelos de datos que extienden de la clase [[yii\base\Model]].
Si estás trabajando con bases de datos (relacionales o NoSQL), es recomendable utilizar [[yii\db\ActiveRecord|ActiveRecord]]
para representar los recursos.
Puedes utilizar [[yii\rest\UrlRule]] para simplificar el enrutamiento de los puntos finales de tu API.
Aunque no es obligatorio, es recomendable que desarrolles tus APIs RESTful como una aplicación separada, diferente de
tu WEB front end y tu back end para facilitar el mantenimiento.

44
docs/guide-es/rest-rate-limiting.md

@ -1,44 +0,0 @@
Limitando el rango (rate)
=========================
Para prevenir el abuso, puedes considerar añadir un *límitación del rango (rate limiting)* para tus APIs. Por ejemplo,
puedes querer limitar el uso del API de cada usuario a un máximo de 100 llamadas al API dentro de un periodo de 10 minutos.
Si se reciben demasiadas peticiones de un usuario dentro del periodo de tiempo declarado, deveríá devolverse una respuesta con código de estado 429 (que significa "Demasiadas peticiones").
Para activar la limitación de rango, la clase [[yii\web\User::identityClass|user identity class]] debe implementar [[yii\filters\RateLimitInterface]].
Este interface requiere la implementación de tres métodos:
* `getRateLimit()`: devuelve el número máximo de peticiones permitidas y el periodo de tiempo (p.e., `[100, 600]` significa que como mucho puede haber 100 llamadas al API dentro de 600 segundos).
* `loadAllowance()`: devuelve el número de peticiones que quedan permitidas y el tiempo (fecha/hora) UNIX
con el último límite del rango que ha sido comprobado.
* `saveAllowance()`: guarda ambos, el número restante de peticiones permitidas y el tiempo actual (fecha/hora) UNIX .
Puedes usar dos columnas en la tabla de usuario para guardar la información de lo permitido y la fecha/hora (timestamp). Con ambas definidas,
entonces `loadAllowance()` y `saveAllowance()` pueden ser utilizados para leer y guardar los valores de las dos columnas correspondientes al actual usuario autenticado.
Para mejorar el desempeño, también puedes considerar almacenar esas piezas de información en caché o almacenamiento NoSQL.
Una vez que la clase de identidad implementa la interfaz requerida, Yii utilizará automáticamente [[yii\filters\RateLimiter]]
configurado como un filtro de acción para que [[yii\rest\Controller]] compruebe el límite de rango. El limitador de rango
lanzará una excepeción [[yii\web\TooManyRequestsHttpException]] cuando el límite del rango sea excedido.
Puedes configurar el limitador de rango
en tu clase controlador REST como sigue:
```php
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['rateLimiter']['enableRateLimitHeaders'] = false;
return $behaviors;
}
```
Cuando se activa el límite de rango, por defecto todas las respuestas serán enviadas con la siguiente cabecera HTTP conteniendo
información sobre el límite actual de rango:
* `X-Rate-Limit-Limit`, el máximo número de peticiones permitidas en un periodo de tiempo
* `X-Rate-Limit-Remaining`, el número de peticiones restantes en el periodo de tiempo actual
* `X-Rate-Limit-Reset`, el número de segundos a esperar para pedir el máximo número de peticiones permitidas
Puedes desactivar estas cabeceras configurando [[yii\filters\RateLimiter::enableRateLimitHeaders]] a `false`,
tal y como en el anterior ejemplo.

190
docs/guide-es/rest-resources.md

@ -1,190 +0,0 @@
Recursos
=========
Las APIs RESTful lo son todos para acceder y manipular *recursos (resources)*. Puedes observar los recursos en el paradigma MVC en [Modelos (models)](structure-models.md) .
Mientras que no hay restricción a cómo representar un recurso, en YII usualmente, puedes representar recursos como objetos de la clase [[yii\base\Model]] o sus clases hijas (p.e. [[yii\db\ActiveRecord]]), por las siguientes razones:
* [[yii\base\Model]] implementa el interface [[yii\base\Arrayable]] , el cual te permite personalizar como exponer los datos de los recursos a travès de las APIs RESTful.
* [[yii\base\Model]] soporta [Validación de entrada (input validation)](input-validation.md), lo cual es muy usado en las APIs RESTful para soportar la entrada de datos.
* [[yii\db\ActiveRecord]] provee un poderoso soporte para el acceso a datos en bases de datos y su manipulación, lo que lo le hace servir perfectamente si sus recursos de datos están en bases de datos.
En esta sección, vamos principalmente a describir como la clase con recursos que extiende de [[yii\base\Model]] (o sus clases hijas) puede especificar qué datos puede ser devueltos vía las APIs RESTful. Si la clase de los recursos no extiende de [[yii\base\Model]], entonces todas las variables públicas miembro serán devueltas.
## Campos (fields) <span id="fields"></span>
Cuando incluimos un recurso en una respuesta de la API RESTful, el recurso necesita ser serializado en una cadena.
Yii divide este proceso en dos pasos. Primero, el recurso es convertido en un array por [[yii\rest\Serializer]].
Segundo, el array es serializado en una cadena en el formato requerido (p.e. JSON, XML) por [[yii\web\ResponseFormatterInterface|response formatters]]. El primer paso es en el que debes de concentrarte principalmente cuando desarrolles una clase de un recurso.
Sobreescribiendo [[yii\base\Model::fields()|fields()]] y/o [[yii\base\Model::extraFields()|extraFields()]],
puedes especificar qué datos, llamados *fields*, en el recursos, pueden ser colocados en el array que le representa.
La diferencia entre estos dos métodos es que el primero especifica el conjunto de campos por defecto que deben ser incluidos en el array que los representa, mientras que el último especifica campos adicionales que deben de ser incluidos en el array si una petición del usuario final para ellos vía el parámetro de consulta `expand`. Por ejemplo,
```
// devuelve todos los campos declarados en fields()
http://localhost/users
// sólo devuelve los campos id y email, provistos por su declaración en fields()
http://localhost/users?fields=id,email
// devuelve todos los campos en fields() y el campo profile siempre y cuando esté declarado en extraFields()
http://localhost/users?expand=profile
// sólo devuelve los campos id, email y profile, siempre y cuando ellos estén declarados en fields() y extraFields()
http://localhost/users?fields=id,email&expand=profile
```
### Sobreescribiendo `fields()` <span id="overriding-fields"></span>
Por defecto, [[yii\base\Model::fields()]] devuelve todos los atributos de los modelos como si fueran campos, mientras [[yii\db\ActiveRecord::fields()]] sólo devuelve los atributos que tengan datos en la base de datos.
Puedes sobreescribir `fields()` para añadir, quitar, renombrar o redefinir campos. El valor de retorno de `fields()` ha de estar en un array. Las claves del array son los nombres de los campos y los valores del array son las correspondientes definiciones de los campos que pueden ser tanto nombres de propiedades/atributos o funciones anónimas que devuelven los correspondientes valores del los campos. En el caso especial de que el nombre de un campo sea el mismo que su definición puedes omitir la clave en el array. Por ejemplo,
```php
// explícitamente lista cada campo, siendo mejor usarlo cuando quieras asegurarte que los cambios
// en una tabla de la base de datos o en un atributo del modelo no provoque el cambio de tu campo (para mantener la compatibilidad anterior).
public function fields()
{
return [
// el nombre de campo es el mismo nombre del atributo
'id',
// el nombre del campo es "email", su atributo se denomina "email_address"
'email' => 'email_address',
// el nombre del campo es "name", su valor es definido está definido por una función anónima de retrollamada (callback)
'name' => function () {
return $this->first_name . ' ' . $this->last_name;
},
];
}
// el ignorar algunos campos, es mejor usarlo cuando heredas de una implementación padre
// y pones en la lista negra (blacklist) algunos campos sensibles
public function fields()
{
$fields = parent::fields();
// quita los campos con información sensible
unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']);
return $fields;
}
```
> Warning: Dado que, por defecto, todos los atributos de un modelo pueden ser incluidos en la devolución del API, debes
> examinar tus datos para estar seguro de que no contiene información sensible. Si se da este tipo de información,
> debes sobreescribir `fields()` para filtrarlos. En el ejemplo anterior, escogemos
> quitar `auth_key`, `password_hash` y `password_reset_token`.
### Sobreescribiendo `extraFields()` <span id="overriding-extra-fields"></span>
Por defecto, [[yii\base\Model::extraFields()]] no devuelve nada, mientras que [[yii\db\ActiveRecord::extraFields()]] devuelve los nombres de las relaciones que tienen datos (populated) obtenidos de la base de datos.
El formato de devolución de los datos de `extraFields()` es el mismo que el de `fields()`. Usualmente, `extraFields()` es principalmente usado para especificar campos cuyos valores sean objetos. Por ejemplo, dado la siguiente declaración de campo,
```php
public function fields()
{
return ['id', 'email'];
}
public function extraFields()
{
return ['profile'];
}
```
la petición `http://localhost/users?fields=id,email&expand=profile` puede devolver los siguientes datos en formato JSON :
```php
[
{
"id": 100,
"email": "100@example.com",
"profile": {
"id": 100,
"age": 30,
}
},
...
]
```
## Enlaces (Links) <span id="links"></span>
[HATEOAS](http://en.wikipedia.org/wiki/HATEOAS), es una abreviación de Hipermedia es el Motor del Estado de la Aplicación (Hypermedia as the Engine of Application State), promueve que las APIs RESTfull devuelvan información que permita a los clientes descubrir las acciones que soportan los recursos devueltos. El sentido de HATEOAS es devolver un conjunto de hiperenlaces con relación a la información, cuando los datos de los recursos son servidos por las APIs.
Las clases con recursos pueden soportar HATEOAS implementando el interfaz [[yii\web\Linkable]] . El interfaz contiene sólo un método [[yii\web\Linkable::getLinks()|getLinks()]] el cual debe de de devolver una lista de [[yii\web\Link|links]].
Típicamente, debes devolver al menos un enlace `self` representando la URL al mismo recurso objeto. Por ejemplo,
```php
use yii\db\ActiveRecord;
use yii\web\Link;
use yii\web\Linkable;
use yii\helpers\Url;
class User extends ActiveRecord implements Linkable
{
public function getLinks()
{
return [
Link::REL_SELF => Url::to(['user/view', 'id' => $this->id], true),
];
}
}
```
Cuando un objeto `User` es devuelto en una respuesta, puede contener un elemento `_links` representando los enlaces relacionados con el usuario, por ejemplo,
```
{
"id": 100,
"email": "user@example.com",
// ...
"_links" => {
"self": {
"href": "https://example.com/users/100"
}
}
}
```
## Colecciones <span id="collections"></span>
Los objetos de los recursos pueden ser agrupados en *collections*. Cada colección contiene una lista de recursos objeto del mismo tipo.
Las colecciones pueden ser representadas como arrays pero, es usualmente más deseable representarlas como [proveedores de datos (data providers)](output-data-providers.md). Esto es así porque los proveedores de datos soportan paginación y ordenación de los recursos, lo cual es comunmente necesario en las colecciones devueltas con las APIs RESTful. Por ejemplo, la siguiente acción devuelve un proveedor de datos sobre los recursos post:
```php
namespace app\controllers;
use yii\rest\Controller;
use yii\data\ActiveDataProvider;
use app\models\Post;
class PostController extends Controller
{
public function actionIndex()
{
return new ActiveDataProvider([
'query' => Post::find(),
]);
}
}
```
Cuando un proveedor de datos está enviando una respuesta con el API RESTful, [[yii\rest\Serializer]] llevará la actual página de los recursos y los serializa como un array de recursos objeto. Adicionalmente, [[yii\rest\Serializer]]
puede incluir también la información de paginación a través de las cabeceras HTTP siguientes:
* `X-Pagination-Total-Count`: Número total de recursos;
* `X-Pagination-Page-Count`: Número de páginas;
* `X-Pagination-Current-Page`: Página actual (iniciando en 1);
* `X-Pagination-Per-Page`: Número de recursos por página;
* `Link`: Un conjunto de enlaces de navegación permitiendo al cliente recorrer los recursos página a página.
Un ejemplo se puede ver en la sección [Inicio rápido (Quick Start)](rest-quick-start.md#trying-it-out).

157
docs/guide-es/rest-response-formatting.md

@ -1,157 +0,0 @@
Formato de Respuesta
====================
Cuando se maneja una petición al API RESTful, una aplicación realiza usualmente los siguientes pasos que están relacionados
con el formato de la respuesta:
1. Determinar varios factores que pueden afectar al formato de la respuesta, como son el tipo de medio, lenguaje, versión, etc.
Este proceso es también conocido como [negociación de contenido (content negotiation)](http://en.wikipedia.org/wiki/Content_negotiation).
2. La conversión de objetos recurso en arrays, como está descrito en la sección [Recursos (Resources)](rest-resources.md).
Esto es realizado por la clase [[yii\rest\Serializer]].
3. La conversión de arrays en cadenas con el formato determinado por el paso de negociación de contenido. Esto es
realizado por los [[yii\web\ResponseFormatterInterface|formatos de respuesta]] registrados
con la propiedad [[yii\web\Response::formatters|formatters]] del
[componente de la aplicación](structure-application-components.md) `response`.
## Negociación de contenido (Content Negotiation) <span id="content-negotiation"></span>
Yii soporta la negociación de contenido a través del filtro [[yii\filters\ContentNegotiator]]. La clase de controlador base
del API RESTful [[yii\rest\Controller]] está equipada con este filtro bajo el nombre `contentNegotiator`.
El filtro provee tanto un formato de respuesta de negociación como una negociación de lenguaje. Por ejemplo, si la petición API RESTful
contiene la siguiente cabecera,
```
Accept: application/json; q=1.0, */*; q=0.1
```
puede obtener una respuesta en formato JSON, como a continuación:
```
$ curl -i -H "Accept: application/json; q=1.0, */*; q=0.1" "http://localhost/users"
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
[
{
"id": 1,
...
},
{
"id": 2,
...
},
...
]
```
Detrás de escena, antes de que sea ejecutada una acción del controlador del API RESTful, el filtro [[yii\filters\ContentNegotiator]]
comprobará la cabecera HTTP `Accept` de la petición y definirá el [[yii\web\Response::format|response format]]
como `'json'`. Después de que la acción sea ejecutada y devuelva el objeto recurso o la colección resultante,
[[yii\rest\Serializer]] convertirá el resultado en un array. Y finalmente, [[yii\web\JsonResponseFormatter]]
serializará el array en una cadena JSON incluyéndola en el cuerpo de la respuesta.
Por defecto, el API RESTful soporta tanto el formato JSON como el XML. Para soportar un nuevo formato, debes configurar
la propiedad [[yii\filters\ContentNegotiator::formats|formats]] del filtro `contentNegotiator` tal y como sigue,
en las clases del controlador del API:
```php
use yii\web\Response;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_HTML;
return $behaviors;
}
```
Las claves de la propiedad `formats` son los tipos MIME soportados, mientras que los valores son los nombres de formato de respuesta correspondientes,
los cuales deben ser soportados en [[yii\web\Response::formatters]].
## Serialización de Datos <span id="data-serializing"></span>
Como hemos descrito antes, [[yii\rest\Serializer]] es la pieza central responsable de convertir
objetos recurso o colecciones en arrays. Reconoce objetos tanto implementando [[yii\base\ArrayableInterface]]
como [[yii\data\DataProviderInterface]]. El primer formateador es implementado principalmente para objetos recursos,
mientras que el segundo para recursos collección.
Puedes configurar el serializador definiendo la propiedad [[yii\rest\Controller::serializer]] con un array de configuración.
Por ejemplo, a veces puedes querer ayudar a simplificar el trabajo de desarrollo del cliente incluyendo información de la paginación
directamente en el cuerpo de la respuesta. Para hacer esto, configura la propiedad [[yii\rest\Serializer::collectionEnvelope]]
como sigue:
```php
use yii\rest\ActiveController;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
public $serializer = [
'class' => 'yii\rest\Serializer',
'collectionEnvelope' => 'items',
];
}
```
Puedes obtener la respuesta que sigue para la petición `http://localhost/users`:
```
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"items": [
{
"id": 1,
...
},
{
"id": 2,
...
},
...
],
"_links": {
"self": {
"href": "http://localhost/users?page=1"
},
"next": {
"href": "http://localhost/users?page=2"
},
"last": {
"href": "http://localhost/users?page=50"
}
},
"_meta": {
"totalCount": 1000,
"pageCount": 50,
"currentPage": 1,
"perPage": 20
}
}
```

92
docs/guide-es/rest-routing.md

@ -1,92 +0,0 @@
Enrutamiento
============
Con las clases de controlador y recurso preparadas, puedes acceder a los recursos usando una URL como
`http://localhost/index.php?r=user/create`, parecida a la que usas con aplicaciones Web normales.
En la práctica, querrás usualmente usar URLs limpias y obtener ventajas de los verbos HTTP.
Por ejemplo, una petición `POST /users` significaría acceder a la acción `user/create`.
Esto puede realizarse fácilmente configurando el componente de la aplicación `urlManager`
como sigue:
```php
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
],
]
```
En comparación con la gestión de URL en las aplicaciones Web, lo principalmente nuevo de lo anterior es el uso de
[[yii\rest\UrlRule]] para el enrutamiento de las peticiones con el API RESTful. Esta clase especial de regla URL creará
un conjunto completo de reglas URL hijas para soportar el enrutamiento y creación de URL para el/los controlador/es especificados.
Por ejemplo, el código anterior es equivalente a las siguientes reglas:
```php
[
'PUT,PATCH users/<id>' => 'user/update',
'DELETE users/<id>' => 'user/delete',
'GET,HEAD users/<id>' => 'user/view',
'POST users' => 'user/create',
'GET,HEAD users' => 'user/index',
'users/<id>' => 'user/options',
'users' => 'user/options',
]
```
Y los siguientes puntos finales del API son mantenidos por esta regla:
* `GET /users`: lista de todos los usuarios página a página;
* `HEAD /users`: muestra ĺa información resumén del usuario listado;
* `POST /users`: crea un nuevo usuario;
* `GET /users/123`: devuelve los detalles del usuario 123;
* `HEAD /users/123`: muestra la información resúmen del usuario 123;
* `PATCH /users/123` y `PUT /users/123`: actualizan al usuario 123;
* `DELETE /users/123`: borra el usuario 123;
* `OPTIONS /users`: muestra los verbos soportados de acuerdo al punto final `/users`;
* `OPTIONS /users/123`: muestra los verbos soportados de acuerdo al punto final `/users/123`.
Puedes configurar las opciones `only` y `except` para explícitamente listar cuáles acciones a soportar o cuáles
deshabilitar, respectivamente. Por ejemplo,
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'except' => ['delete', 'create', 'update'],
],
```
También puedes configurar las propiedades `patterns` o `extraPatterns` para redifinir patrones existentes o añadir nuevos soportados por esta regla.
Por ejemplo, para soportar una nueva acción `search` por el punto final `GET /users/search`, configura la opción `extraPatterns` como sigue,
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'extraPatterns' => [
'GET search' => 'search',
],
]
```
Puedes haber notado que el ID del controlador `user` aparece en formato plural `users` en los puntos finales de las URLs.
Esto se debe a que [[yii\rest\UrlRule]] automáticamente pluraliza los IDs de los controladores al crear reglas URL hijas.
Puedes desactivar este comportamiento definiendo la propiedad [[yii\rest\UrlRule::pluralize]] como `false`.
> Info: La pluralización de los IDs de los controladores es realizada por [[yii\helpers\Inflector::pluralize()]]. Este método respeta
reglas especiales de pluralización. Por ejemplo, la palabra `box` (caja) será pluralizada como `boxes` en vez de `boxs`.
En caso de que la pluralización automática no encaje en tus requerimientos, puedes además configurar la propiedad
[[yii\rest\UrlRule::controller]] para especificar exlpícitamente cómo mapear un nombre utilizado en un punto final URL
a un ID de controlador. Por ejemplo, el siguiente código mapea el nombre `u` al ID del controlador `user`.
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => ['u' => 'user'],
]
```

111
docs/guide-es/rest-versioning.md

@ -1,111 +0,0 @@
Versionado
==========
Una buena API ha de ser *versionada*: los cambios y las nuevas características son implementadas en las nuevas versiones del API, en vez de estar continuamente modificando sólo una versión. Al contrario que en las aplicaciones Web, en las cuales tienes total control del código de ambas partes lado del cliente y lado del servidor,
las APIs están destinadas a ser usadas por los clientes fuera de tu control. Por esta razón, compatibilidad hacia atrás (BC Backward compatibility)
de las APIs ha de ser mantenida siempre que sea posible. Si es necesario un cambio que puede romper la BC, debes de introducirla en la nueva versión del API, e incrementar el número de versión. Los clientes que la usan pueden continuar usando la antigua versión de trabajo del API; los nuevos y actualizados clientes pueden obtener la nueva funcionalidad de la nueva versión del API.
> Tip: referirse a [Semántica del versionado](http://semver.org/)
para más información en el diseño del número de versión del API.
Una manera común de implementar el versionado de la API es embeber el número de versión en las URLs de la API.
Por ejemplo, `http://example.com/v1/users` se refiere al punto final `/users` de la versión 1 de la API.
Otro método de versionado de la API,
la cual está ganando predominancia recientemente, es poner el número de versión en las cabeceras de la petición HTTP. Esto se suele hacer típicamente a través la cabecera `Accept`:
```
// vía parámetros
Accept: application/json; version=v1
// vía de el tipo de contenido del proveedor
Accept: application/vnd.company.myapp-v1+json
```
Ambos métodos tienen sus pros y sus contras, y hay gran cantidad de debates sobre cada uno. Debajo puedes ver una estrategia
práctica para el versionado de la API que es una mezcla de estos dos métodos:
* Pon cada versión superior de la implementación de la API en un módulo separado cuyo ID es el número de la versión mayor (p.e. `v1`, `v2`).
Naturalmente, las URLs de la API contendrán números de versión mayores.
* Dentro de cada versión mayor (y por lo tanto, dentro del correspondiente módulo), usa la cabecera de HTTP `Accept`
para determinar el número de la versión menor y escribe código condicional para responder a la menor versión como corresponde.
Para cada módulo sirviendo una versión mayor, el módulo debe incluir las clases de recursos y y controladores
que especifican la versión. Para separar mejor la responsabilidad del código, puedes conservar un conjunto común de
clases base de recursos y controladores, y hacer subclases de ellas en cada versión individual del módulo. Dentro de las subclases,
impementa el código concreto como por ejemplo `Model::fields()`.
Tu código puede estar organizado como lo que sigue:
```
api/
common/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
modules/
v1/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
v2/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
```
La configuración de tu aplicación puede tener este aspecto:
```php
return [
'modules' => [
'v1' => [
'basePath' => '@app/modules/v1',
'controllerNamespace' => 'app\modules\v1\controllers',
],
'v2' => [
'basePath' => '@app/modules/v2',
'controllerNamespace' => 'app\modules\v2\controllers',
],
],
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => ['v1/user', 'v1/post']],
['class' => 'yii\rest\UrlRule', 'controller' => ['v2/user', 'v2/post']],
],
],
],
];
```
Como consecuencia del código anterior, `http://example.com/v1/users` devolverá la lista de usuarios en la versión 1, mientras
`http://example.com/v2/users` devolverá la versión 2 de los usuarios.
Gracias a los módulos, el código de las diferentes principales versiones puede ser aislado. Pero los módulos hacen posible
reutilizar el código a través de los módulos vía clases base comunes y otros recursos compartidos.
Para tratar con versiones menores, puedes tomar ventaja de la característica de negociación de contenido
provista por el comportamiento (behavior) [[yii\filters\ContentNegotiator|contentNegotiator]]. El comportamiento `contentNegotiator`
definirá la propiedad [[yii\web\Response::acceptParams]] cuando determina qué tipo
de contenido soportar.
Por ejemplo, si una petición es enviada con la cabecera HTTP `Accept: application/json; version=v1`,
después de la negociación de contenido, [[yii\web\Response::acceptParams]] contendrá el valor `['version' => 'v1']`.
Basado en la información de versión contenida en `acceptParams`, puedes escribir código condicional en lugares
como acciones, clases de recursos, serializadores, etc. para proveer la funcionalidad apropiada.
Dado que por definición las versiones menores requireren mantener la compatibilidad hacia atrás, con suerte no tendrás demasiadas
comprobaciones de versión en tu código. De otra manera, probablemente puede ocurrir que necesites crear una versión mayor.

14
docs/guide-fr/README.md

@ -124,20 +124,6 @@ Cache
* [Cache HTTP](caching-http.md)
Services Web RESTful
--------------------
* [Démarrage rapide](rest-quick-start.md)
* [Ressources](rest-resources.md)
* [Contrôleurs](rest-controllers.md)
* [Gestion des routes](rest-routing.md)
* [Formattage des réponses](rest-response-formatting.md)
* [Authentification](rest-authentication.md)
* [Limiter le taux d'utilisation](rest-rate-limiting.md)
* [Gestion des versions](rest-versioning.md)
* [Gestion des erreurs](rest-error-handling.md)
Outils de développement
-----------------------

14
docs/guide-pl/README.md

@ -129,20 +129,6 @@ Pamięć podręczna
* [Pamięć podręczna HTTP](caching-http.md)
Webserwisy z wykorzystaniem REST
--------------------------------
* [Szybki start](rest-quick-start.md)
* [Zasoby](rest-resources.md)
* [Kontrolery](rest-controllers.md)
* [Routing](rest-routing.md)
* [Formatowanie odpowiedzi](rest-response-formatting.md)
* [Uwierzytelnianie](rest-authentication.md)
* [Limit użycia](rest-rate-limiting.md)
* [Wersjonowanie](rest-versioning.md)
* [Obsługa błędów](rest-error-handling.md)
Narzędzia wspomagające tworzenie aplikacji
------------------------------------------

90
docs/guide-pl/rest-error-handling.md

@ -1,90 +0,0 @@
Obsługa błędów
==============
Podczas obsługi żądania RESTfulowego API, w przypadku wystąpienia błędu w zapytaniu użytkownika lub gdy stanie się coś nieprzewidywanego
z serwerem, możesz po prostu rzucić wyjątkiem, aby powiadomić użytkownika, że coś poszło nieprawidłowo.
Jeśli możesz zidentyfikować przyczynę błędu (np. żądany zasób nie istnieje), powinieneś rozważyć rzucenie wyjątkiem razem z odpowiednim kodem statusu HTTP
(np. [[yii\web\NotFoundHttpException|NotFoundHttpException]] odpowiada statusowi o kodzie 404).
Yii wyśle odpowiedź razem z odpowiadającym jej kodem i treścią statusu HTTP. Yii dołączy również do samej odpowiedzi zserializowaną reprezentację
wyjątku. Przykładowo:
```
HTTP/1.1 404 Not Found
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
```
Poniższa lista zawiera kody statusów HTTP, które są używane przez Yii REST framework:
* `200`: OK. Wszystko działa w porządku.
* `201`: Zasób został poprawnie stworzony w odpowiedzi na żądanie `POST`. Nagłówek `Location` zawiera URL kierujący do nowoutworzonego zasobu.
* `204`: Żądanie zostało poprawnie przetworzone, ale odpowiedź nie zawiera treści (jak w przypadku żądania `DELETE`).
* `304`: Zasób nie został zmodyfikowany. Można użyć wersji przetrzymywanej w pamięci podręcznej.
* `400`: Nieprawidłowe żądanie. Może być spowodowane przez wiele czynników po stronie użytkownika, takich jak przekazanie nieprawidłowych danych JSON,
nieprawidłowych parametrów akcji, itp.
* `401`: Nieudana autentykacja.
* `403`: Autoryzowany użytkownik nie ma uprawnień do danego punktu końcowego API.
* `404`: Żądany zasób nie istnieje.
* `405`: Niedozwolona metoda. Sprawdź nagłówek `Allow`, aby poznać dozwolone metody HTTP.
* `415`: Niewspierany typ mediów. Żądany typ zawartości lub numer wersji jest nieprawidłowy.
* `422`: Nieudana walidacja danych (dla przykładu w odpowiedzi na żądanie `POST`). Sprawdź treść odpowiedzi, aby poznać szczegóły błędu.
* `429`: Zbyt wiele żądań. Żądanie zostało odrzucone z powodu osiagnięcia limitu użycia.
* `500`: Wewnętrzny błąd serwera. To może być spowodowane wewnętrznymi błędami programu.
## Modyfikowanie błędnej odpowiedzi <span id="customizing-error-response"></span>
Czasem wymagane może być dostosowanie domyślnego formatu błędnej odpowiedzi. Dla przykładu, zamiast używać różnych statusów HTTP dla oznaczenia różnych błędów,
można serwować zawsze status 200 i dodawać prawidłowy kod statusu HTTP jako część struktury JSON w odpowiedzi, jak pokazano to poniżej:
```
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"success": false,
"data": {
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
}
```
Aby osiągnąć powyższy efekt, należy skonfigurować odpowiedź na event `beforeSend` dla komponentu `response` w aplikacji:
```php
return [
// ...
'components' => [
'response' => [
'class' => 'yii\web\Response',
'on beforeSend' => function ($event) {
$response = $event->sender;
if ($response->data !== null && Yii::$app->request->get('suppress_response_code')) {
$response->data = [
'success' => $response->isSuccessful,
'data' => $response->data,
];
$response->statusCode = 200;
}
},
],
],
];
```
Powyższy kod zreformatuje odpowiedź (zarówno typu sukces jak i błąd), kiedy `suppress_response_code` zostanie przekazane jako parametr `GET`.

37
docs/guide-pl/rest-rate-limiting.md

@ -1,37 +0,0 @@
Limit użycia
============
W celu zapobiegnięcia nadużyciom, powinno się rozważyć wprowadzenie *limitu użycia* swojego API. Może to być na przykład ograniczenie
do maksymalnie 100 zapytań do API dla każdego użytkownika w czasie 10 minut. Jeśli użytkownik przekroczy ten limit w zadanym czasie,
należy zwrócić odpowiedź ze statusem 429 (oznaczającym "Zbyt dużo zapytań").
Aby ustalić limit użycia, [[yii\web\User::identityClass|klasa identyfikująca użytkownika]] powinna zaimplementować [[yii\filters\RateLimitInterface|RateLimitInterface]].
Interfejs ten wymaga dodania trzech metod:
* `getRateLimit()`: zwraca maksymalną liczbę zapytań i okres czasu (np. `[100, 600]` oznacza maksymalnie 100 zapytań do API w czasie 600 sekund).
* `loadAllowance()`: zwraca liczbę pozostałych dozwolonych zapytań z limitu i uniksowy znacznik czasu wskazujący datę ostatniego sprawdzenia limitu.
* `saveAllowance()`: zapisuje liczbę pozostałych dozwolonych zapytań i aktualny uniksowy znacznik czasu.
Do celów obsługi powyższych metod można wykorzystać dwie dodatkowe kolumny w bazie danych użytkowników dla liczby dokonanych połączeń i znacznika czasu.
Po ustaleniu tych wartości, metody `loadAllowance()` i `saveAllowance()` mogą być poprawnie zaimplementowane do odczytu i zapisu tych wartości dla aktualnego
zautoryzowanego użytkownika. Aby zwiększyć wydajność tego mechanizmu, należy rozważyć użycie pamięci podręcznej lub bazy typu NoSQL.
Po zaimplemetowaniu wymaganego interfejsu, Yii automatycznie użyje [[yii\filters\RateLimiter|RateLimiter]], skonfigurowanego jako filtr akcji dla [[yii\rest\Controller|Controller]],
aby pilnować limitu użycia API. Mechanizm rzuci wyjątek [[yii\web\TooManyRequestsHttpException|TooManyRequestsHttpException]], kiedy limit zostanie przekroczony.
Po dodaniu limitu, każda odpowiedź będzie domyślnie zawierała następujące nagłówki HTTP, zawierające informacje o aktualnym użyciu limitu:
* `X-Rate-Limit-Limit`, maksymalna liczba zapytań w zadanym okresie czasu,
* `X-Rate-Limit-Remaining`, liczba pozostałych dozwolonych zapytań z limitu w aktualnym okresie czasu,
* `X-Rate-Limit-Reset`, liczba sekund, którą należy odczekać, aby uzyskać ponownie maksymalną liczbę zapytań z limitu.
Wysyłanie powyższych nagłówków można wyłączyć konfigurując [[yii\filters\RateLimiter::enableRateLimitHeaders|enableRateLimitHeaders]] w klasie kontrolera REST jak w poniższym przykładzie.
```php
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['rateLimiter']['enableRateLimitHeaders'] = false;
return $behaviors;
}
```

90
docs/guide-pl/rest-routing.md

@ -1,90 +0,0 @@
Routing
=======
Po przygotowaniu klas zasobów i kontrolerów dostęp do nich można uzyskać w ten sam sposób, jak w przypadku zwykłej aplikacji, używając URL np.
`http://localhost/index.php?r=user/create`.
W praktyce zwykle chcemy skorzystać z opcji "ładnych" URLi i metod HTTP.
Przykładowo żądanie `POST /users` może oznaczać wywołanie akcji `user/create`, co możemy uzyskać w łatwy sposób konfigurując
[komponent aplikacji](structure-application-components.md) `urlManager` w pliku konfiguracyjnym jak poniżej:
```php
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
],
]
```
Porównując to z menadżerem URLi dla aplikacji Web, główną nowością tutaj jest użycie [[yii\rest\UrlRule|UrlRule]] do routingu RESTfulowych zasobów API.
Ta specjalna klasa zasad URL stworzy cały zestaw potomnych zasad URL obsługujących routing i tworzenie URLi dla wyznaczonego kontrolera.
Dla przykładu, kod powyżej jest zgrubnym odpowiednikiem następujących zasad:
```php
[
'PUT,PATCH users/<id>' => 'user/update',
'DELETE users/<id>' => 'user/delete',
'GET,HEAD users/<id>' => 'user/view',
'POST users' => 'user/create',
'GET,HEAD users' => 'user/index',
'users/<id>' => 'user/options',
'users' => 'user/options',
]
```
I poniższe punkty końcowe API są obsługiwane przez tę zasadę:
* `GET /users`: lista wszystkich użytkowników strona po stronie;
* `HEAD /users`: pokazuje streszczenie informacji listy użytkowników;
* `POST /users`: tworzy nowego użytkownika;
* `GET /users/123`: zwraca szczegóły na temat użytkownika 123;
* `HEAD /users/123`: zwraca streszczenie informacji o użytkowniku 123;
* `PATCH /users/123` i `PUT /users/123`: aktualizuje użytkownika 123;
* `DELETE /users/123`: usuwa użytkownika 123;
* `OPTIONS /users`: pokazuje obsługiwane metody dla punktu końcowego `/users`;
* `OPTIONS /users/123`: pokazuje obsługiwane metody dla punktu końcowego `/users/123`.
Możesz skonfigurować opcje `only` i `except`, aby wskazać listę akcji, które mają być odpowiednio: tylko obsługiwane lub pominięte.
Przykładowo,
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'except' => ['delete', 'create', 'update'],
],
```
Dodatkowo można dodać opcję `patterns` lub `extraPatterns`, aby zredefiniować istniejące wzorce lub dodać nowe obsługiwane przez tę zasadę.
Dla przykładu, aby dodać obsługę nowej akcji `search` dla punktu końcowego `GET /users/search`, skonfiguruj opcję `extraPatterns` jak następuje,
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'extraPatterns' => [
'GET search' => 'search',
],
]
```
Na pewno zwróciłeś uwagę na to, że ID kontrolera `user` występuje tu w formie mnogiej jako `users` dla URLi punktu końcowego.
Dzieje się tak, ponieważ [[yii\rest\UrlRule|UrlRule]] automatycznie przechodzi na formę mnogą dla ID kontrolerów podczas tworzenia potomnych zasad URL.
Zachowanie to można wyłączyć ustawiając [[yii\rest\UrlRule::pluralize|pluralize]] na `false`.
> Info: forma mnoga ID kontrolerów jest tworzona poprzez metodę [[yii\helpers\Inflector::pluralize()|pluralize()]]. Uwzględnia ona specjalne zasady tworzenia form mnogich.
> Dla przykładu, od słowa `box` zostanie utworzona liczba mnoga `boxes` a nie `boxs`.
W przypadku, gdy mechanizm automatycznego tworzenia formy mnogiej nie spełnia Twoich oczekiwań, możesz również skonfigurować właściwość
[[yii\rest\UrlRule::controller|controller]], aby bezpośrednio określić w jaki sposób nazwa użyta w punkcie końcowym URLi ma być zmapowana na ID kontrolera.
Dla przykładu, poniższy kod mapuje nazwę `u` na ID kontrolera `user`.
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => ['u' => 'user'],
]
```

112
docs/guide-pl/rest-versioning.md

@ -1,112 +0,0 @@
Wersjonowanie
=============
Cechą dobrego API jest jego *wersjonowanie*: zmiany i nowe funkcjonalności powinny być implementowane w nowych wersjach API, zamiast
ciągłych modyfikacji jednej już istniejącej. W przeciwieństwie do aplikacji Web, nad którymi ma się pełną kontrolę zarówno po stronie
klienta, jak i serwera, nad API zwykle nie posiada się kontroli po stronie klienta. Z tego powodu niezwykle istotnym jest, aby zachować
pełną wsteczną kompatybilność (BC = backward compatibility), kiedy to tylko możliwe. Jeśli konieczne jest wprowadzenie zmiany, która
może nie spełniać BC, należy wprowadzić ją w nowej wersji API, z kolejnym numerem. Istniejące klienty mogą wciąż używać starej,
działającej wersji API, a nowe lub uaktualnione klienty mogą otrzymać nową funkcjonalność oferowaną przez kolejną wersję API.
> Tip: Zapoznaj się z [Wersjonowaniem semantycznym](http://semver.org/lang/pl/), aby uzyskać więcej informacji na temat nazewnictwa
numerów wersji.
Jedną z często spotykanych implementacji wersjonowania API jest dodawanie numeru wersji w adresach URL API.
Dla przykładu `http://example.com/v1/users` oznacza punkt końcowy `/users` API w wersji 1.
Inną metodą wersjonowania API, która zyskuje ostatnio popularność, jest umieszczanie numeru wersji w nagłówkach HTTP żądania. Zwykle
używa się do tego nagłówka `Accept`:
```
// poprzez parametr
Accept: application/json; version=v1
// poprzez dostarczany typ zasobu
Accept: application/vnd.company.myapp-v1+json
```
Obie metody mają swoje wady i zalety i wciąż prowadzone są dyskusje na ich temat. Poniżej prezentujemy strategię wersjonowania, która
w praktyczny sposób łączy je obie:
* Umieść każdą główną wersję implementacji API w oddzielnym module, którego ID odpowiada numerowi głównej wersji (np. `v1`, `v2`).
Adresy URL API będą zawierały numery głównych wersji.
* Wewnątrz każdej głównej wersji (i w związku z tym w każdym odpowiadającym jej module), użyj nagłówka HTTP `Accept`, aby określić
pomniejszy numer wersji i napisz warunkowy kod odpowiadający temu numerowi.
Każdy moduł obsługujący główną wersję powinien zawierać klasy zasobów i kontrolerów odpowiednie dla tej wersji. W celu lepszego
rozdzielenia zadań kodu, możesz trzymać razem zestaw podstawowych wspólnych klas zasobów i kontrolerów w jednym miejscu i rozdzielać go
na podklasy w każdym module wersji. W podklasie implementujesz bazowy kod, taki jak `Model::fields()`.
Struktura Twojego kodu może wyglądać jak poniższa:
```
api/
common/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
modules/
v1/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
Module.php
v2/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
Module.php
```
Konfiguracja Twojej aplikacji mogłaby wyglądać następująco:
```php
return [
'modules' => [
'v1' => [
'class' => 'app\modules\v1\Module',
],
'v2' => [
'class' => 'app\modules\v2\Module',
],
],
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => ['v1/user', 'v1/post']],
['class' => 'yii\rest\UrlRule', 'controller' => ['v2/user', 'v2/post']],
],
],
],
];
```
Rezultatem powyższego kodu będzie skierowanie pod adresem `http://example.com/v1/users` do listy użytkowników w wersji 1, podczas gdy
`http://example.com/v2/users` pokaże użytkowników w wersji 2.
Dzięki podziałowi na moduły, kod różnych głównych wersji może być dobrze izolowany, ale jednocześnie wciąż możliwe jest ponowne
wykorzystanie wspólnego kodu poprzez wspólną bazę klas i dzielonych zasobów.
Aby prawidłowo obsłużyć pomniejsze numery wersji, możesz wykorzystać funkcjonalność negocjatora zawartości dostarczaną przez behavior
[[yii\filters\ContentNegotiator|contentNegotiator]]. Ustawi on właściwość [[yii\web\Response::acceptParams]], kiedy już zostanie
ustalone, który typ zasobów wspierać.
Przykładowo, jeśli żądanie jest wysłane z nagłówkiem HTTP `Accept: application/json; version=v1`, po negocjacji zawartości
[[yii\web\Response::acceptParams]] będzie zawierać wartość `['version' => 'v1']`.
Bazując na informacji o wersji w `acceptParams`, możesz napisać obsługujący ją warunkowy kod w miejscach takich jak akcje, klasy
zasobów, serializatory, itp., aby zapewnić odpowiednią funkcjonalność.
Ponieważ pomniejsze wersje z definicji wymagają zachowania wstecznej kompatybilności, w kodzie nie powinno znaleźć się zbyt wiele
miejsc, gdzie numer wersji będzie sprawdzany. W przeciwnym wypadku możliwe, że konieczne będzie utworzenie kolejnej głównej wersji API.

14
docs/guide-pt-BR/README.md

@ -126,20 +126,6 @@ Cache
* [Cache HTTP](caching-http.md)
Web Services RESTful
------------------------
* [Introdução](rest-quick-start.md)
* [Recursos](rest-resources.md)
* [Controllers (Controladores)](rest-controllers.md)
* [Roteamento](rest-routing.md)
* [Formatando Respostas](rest-response-formatting.md)
* [Autenticação](rest-authentication.md)
* [Limitador de Acesso](rest-rate-limiting.md)
* [Versionamento](rest-versioning.md)
* [Tratamento de Erros](rest-error-handling.md)
Ferramentas de Desenvolvimento
------------------------------

104
docs/guide-pt-BR/rest-authentication.md

@ -1,104 +0,0 @@
Autenticação
==============
Ao contrário de aplicações Web, APIs RESTful são geralmente stateless, o que significa que as sessões ou os cookies não devem ser utilizados. Portanto, cada requisição deve vir com algum tipo de credencial de autenticação pois o estado de autenticação do usuário não pode ser mantido por sessões ou cookies. Uma prática comum é enviar um token de acesso secreto com cada solicitação para autenticar o usuário. Uma vez que um token de acesso pode ser utilizado para identificar de forma exclusiva e autenticar um usuário. **Solicitações de API devem sempre ser enviadas via HTTPS para evitar ataques man-in-the-middle (MitM)**.
Existem diferentes maneiras de enviar um token de acesso:
* [Autenticação Básica HTTP](http://en.wikipedia.org/wiki/Basic_access_authentication): o token de acesso é enviado como um nome de usuário. Isso só deve ser usado quando um token de acesso puder ser armazenado com segurança no lado do consumidor da API. Por exemplo, o consumidor API é um programa executado em um servidor.
* Parâmetro de consulta da URL: o token de acesso é enviado como um parâmetro de consulta na URL da API, ex., `https://example.com/users?access-token=xxxxxxxx`. Como a maioria dos servidores Web manterão os parâmetros de consulta nos logs do servidor, esta abordagem deve ser utilizada principalmente para servir requisições `JSONP` que não pode usar cabeçalhos HTTP para enviar tokens de acesso.
* [OAuth 2](http://oauth.net/2/): o token de acesso é obtido pelo consumidor a partir de um servidor de autorização e enviado para o servidor da API via [HTTP Bearer Tokens] (http://tools.ietf.org/html/rfc6750), de acordo com o protocolo OAuth2.
Yii suporta todos os métodos de autenticação descritos acima. Você também pode criar facilmente um novo método de autenticação.
Para ativar a autenticação nas suas APIs, siga os seguintes passos:
1. Configure o [componente de aplicação](structure-application-components.md) `user`:
- Defina a propriedade [[yii\web\User::enableSession|enableSession]] como `false`.
- Defina a propriedade [[yii\web\User::loginUrl|loginUrl]] como `null` para mostrar o erro HTTP 403 em vez de redirecionar para a página de login.
2. Especificar quais métodos de autenticação você planeja usar configurando o behavior `authenticator` na sua classe controller REST.
3. Implemente [[yii\web\IdentityInterface::findIdentityByAccessToken()]] na sua [[yii\web\User::identityClass|classe de identidade do usuário]].
Passo 1 não é obrigatório, mas é recomendado para APIs RESTful stateless. Quando [[yii\web\User::enableSession|enableSession]] está marcado como falso, o status de autenticação de usuário NÃO será mantido entre as requisições usando sessões. Em lugar disso, autenticação será realizada para cada requisição, que é realizado no passo 2 e 3.
> Dica: Você pode configurar [[yii\web\User::enableSession|enableSession]] do componente `user`
> nas configurações da aplicação se você estiver desenvolvendo APIs RESTful para sua aplicação. Se você desenvolver
> APIs RESTful como um módulo, você pode colocar a seguinte linha no método `init()` do módulo, conforme exemplo a seguir:
>
> ```php
> public function init()
> {
> parent::init();
> \Yii::$app->user->enableSession = false;
> }
> ```
Por exemplo, para usar autenticação HTTP básica, você pode configurar o behavior `authenticator` como o seguinte:
```php
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpBasicAuth::class,
];
return $behaviors;
}
```
Se você quiser dar suporte a todos os três métodos de autenticação explicado acima, você pode utilizar o `CompositeAuth` conforme mostrado a seguir:
```php
use yii\filters\auth\CompositeAuth;
use yii\filters\auth\HttpBasicAuth;
use yii\filters\auth\HttpBearerAuth;
use yii\filters\auth\QueryParamAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => CompositeAuth::class,
'authMethods' => [
HttpBasicAuth::class,
HttpBearerAuth::class,
QueryParamAuth::class,
],
];
return $behaviors;
}
```
Cada elemento em `authMethods` deve ser o nome de uma classe de método de autenticação ou um array de configuração.
Implementação de `findIdentityByAccessToken()` é específico por aplicação. Por exemplo, em cenários simples quando cada usuário só pode ter um token de acesso, você pode armazenar o token de acesso em uma coluna `access_token` na tabela `user`. O método pode então ser facilmente implementado na classe `User` como o seguinte:
```php
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
class User extends ActiveRecord implements IdentityInterface
{
public static function findIdentityByAccessToken($token, $type = null)
{
return static::findOne(['access_token' => $token]);
}
}
```
Após a autenticação ser ativada, conforme descrito acima, para todas as requisições da API, o controller requisitado irá tentar autenticar o usuário no passo `beforeAction()`.
Se a autenticação retornar com sucesso, o controller irá executar outras verificações (tais como limitação de taxa, autorização) e então executará a ação. As informações de identidade do usuário autenticado podem ser recuperadas através de `Yii::$app->user->identity`.
Se a autenticação falhar, uma resposta HTTP com status 401 será enviado de volta junto com outros cabeçalhos apropriados (tal como um `WWW-Authenticate` cabeçalho HTTP para Autenticação Básica).
## Autorização <span id="authorization"></span>
Após um usuário se autenticar, você provavelmente vai querer verificar se ele ou ela tem a permissão para executar a ação do recurso solicitado. Este processo é chamado de *autorização* que é tratada em pormenor na seção de [Autorização](security-authorization.md).
Se o seu controller estende de [[yii\rest\ActiveController]], você pode sobrescrever o método [[yii\rest\Controller::checkAccess()|checkAccess()]] para executar a verificação de autorização. O método será chamado pelas ações incorporadas fornecidas pelo [[yii\rest\ActiveController]].

133
docs/guide-pt-BR/rest-controllers.md

@ -1,133 +0,0 @@
Controllers (Controladores)
===========
Depois de criar as classes de recursos e especificar como os dados de recursos devem ser formatados, a próxima coisa a fazer é criar ações do controller para expor os recursos para os usuários finais através das APIs RESTful.
O Yii fornece duas classes básicas de controller para simplificar seu trabalho de criar ações RESTful: [[yii\rest\Controller]] e [[yii\rest\ActiveController]]. A diferença entre os dois controllers é que o último fornece um conjunto padrão de ações que são especificamente concebidos para lidar com recursos do [Active Record](db-active-record.md). Então, se você estiver usando [Active Record](db-active-record.md) e está confortável com as ações fornecidas, você pode considerar estender suas classes de controller de [[yii\rest\ActiveController]], que permitirá criar poderosas APIs RESTful com um mínimo de código.
Ambas classes [[yii\rest\Controller]] e [[yii\rest\ActiveController]] fornecem os seguintes recursos, algumas das quais serão descritas em detalhes nas próximas seções:
* Validação de Método HTTP;
* [Negociação de conteúdo e formatação de dados](rest-response-formatting.md);
* [Autenticação](rest-authentication.md);
* [Limitação de taxa](rest-rate-limiting.md).
O [[yii\rest\ActiveController]] oferece também os seguintes recursos:
* Um conjunto de ações comumente necessárias: `index`, `view`, `create`, `update`, `delete`, `options`;
* Autorização do usuário em relação à ação solicitada e recursos.
## Criando Classes Controller <span id="creating-controller"></span>
Ao criar uma nova classe de controller, uma convenção na nomenclatura da classe é usar o nome do tipo de recurso no singular. Por exemplo, para disponibilizar as informações do usuário, o controlador pode ser nomeado como `UserController`. Criar uma nova ação é semelhante à criação de uma ação de uma aplicação Web. A única diferença é que em vez de renderizar o resultado usando uma view e chamando o método `render()`, para ações RESTful você retorna diretamente os dados. O [[yii\rest\Controller::serializer|serializer]] e o [[yii\web\Response|objeto response]] vão converter os dados originais para o formato solicitado. Por exemplo:
```php
public function actionView($id)
{
return User::findOne($id);
}
```
## Filtros <span id="filters"></span>
A maioria dos recursos da API RESTful fornecidos por [[yii\rest\Controller]] são implementadas por [filtros](structure-filters.md).
Em particular, os seguintes filtros serão executados na ordem em que estão listados:
* [[yii\filters\ContentNegotiator|contentNegotiator]]: suporta a negociação de conteúdo, a ser explicado na seção [Formatação de Resposta](rest-response-formatting.md);
* [[yii\filters\VerbFilter|verbFilter]]: suporta validação de métodos HTTP;
* [[yii\filters\auth\AuthMethod|authenticator]]: suporta autenticação de usuários, que será explicado na seção [Autenticação](rest-authentication.md);
* [[yii\filters\RateLimiter|rateLimiter]]: suporta limitação de taxa, que será explicado na seção
[Limitação de taxa](rest-rate-limiting.md).
Estes filtros são declarados no método [[yii\rest\Controller::behaviors()|behaviors()]].
Você pode sobrescrever esse método para configurar alguns filtros, desativar outros, ou adicionar seus próprios filtros. Por exemplo, se você precisar somente de autenticação básica de HTTP, poderá utilizar o seguinte código:
```php
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpBasicAuth::class,
];
return $behaviors;
}
```
## Estendendo `ActiveController` <span id="extending-active-controller"></span>
Se a sua classe controller estende de [[yii\rest\ActiveController]], você deve configurar a propriedade [[yii\rest\ActiveController::modelClass|modelClass]] para ser o nome da classe de recurso que você pretende servir através deste controller. A classe deve estender de [[yii\db\ActiveRecord]].
### Customizando Ações <span id="customizing-actions"></span>
Por padrão, o [[yii\rest\ActiveController]] fornece as seguintes ações:
* [[yii\rest\IndexAction|index]]: recursos de lista página por página;
* [[yii\rest\ViewAction|view]]: retorna os detalhes de um recurso especificado;
* [[yii\rest\CreateAction|create]]: cria um novo recurso;
* [[yii\rest\UpdateAction|update]]: atualiza um recurso existente;
* [[yii\rest\DeleteAction|delete]]: excluir o recurso especificado;
* [[yii\rest\OptionsAction|options]]: retorna os métodos HTTP suportados.
Todas essas ações são declaradas através do método [[yii\rest\ActiveController::actions()|actions()]]. Você pode configurar essas ações ou desativar algumas delas, sobrescrevendo o método `actions()`, como mostrado a seguir:
```php
public function actions()
{
$actions = parent::actions();
// desabilita as ações "delete" e "create"
unset($actions['delete'], $actions['create']);
// customiza a preparação do data provider com o método "prepareDataProvider()"
$actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider'];
return $actions;
}
public function prepareDataProvider()
{
// preparar e retornar um data provider para a ação "index"
}
```
Por favor, consulte as referências de classe para classes de ação individual para saber as opções de configuração que estão disponíveis.
### Executando Verificação de Acesso <span id="performing-access-check"></span>
Ao disponibilizar recursos por meio de APIs RESTful, muitas vezes você precisa verificar se o usuário atual tem permissão para acessar e manipular o(s) recurso(s) solicitado(s). Com o [[yii\rest\ActiveController]], isso pode ser feito sobrescrevendo o método [[yii\rest\ActiveController::checkAccess()|checkAccess()]] conforme a seguir:
```php
/**
* Verifica os privilégios do usuário corrente.
*
* Este método deve ser sobrescrito para verificar se o usuário atual tem o privilégio
* para executar a ação especificada diante do modelo de dados especificado.
* se o usuário não tiver acesso, uma [[ForbiddenHttpException]] deve ser lançada.
*
* @param string $action o ID da ação a ser executada
* @param \yii\base\Model $model o model a ser acessado. Se `null`, isso significa que nenhum model específico está sendo acessado.
* @param array $params parâmetros adicionais
* @throws ForbiddenHttpException se o usuário não tiver acesso
*/
public function checkAccess($action, $model = null, $params = [])
{
// verifica se o usuário pode acessar $action and $model
// lança a ForbiddenHttpException se o acesso for negado
if ($action === 'update' || $action === 'delete') {
if ($model->author_id !== \Yii::$app->user->id)
throw new \yii\web\ForbiddenHttpException(sprintf('You can only %s articles that you\'ve created.', $action));
}
}
```
O método `checkAccess()` será chamado pelas ações padrões do [[yii\rest\ActiveController]]. Se você criar novas ações e também desejar executar a verificação de acesso, deve chamar esse método explicitamente nas novas ações.
> Dica: Você pode implementar `checkAccess()` usando o [componente de Role-Based Access Control (RBAC)](security-authorization.md).

85
docs/guide-pt-BR/rest-error-handling.md

@ -1,85 +0,0 @@
Tratamento de Erros
==============
Ao manusear uma requisição da API RESTful, se existir um erro na requisição do usuário ou se alguma coisa inesperada acontecer no servidor, você pode simplesmente lançar uma exceção para notificar o usuário de que algo deu errado.
Se você puder identificar a causa do erro (ex., o recurso requisitado não existe), você deve considerar lançar uma exceção juntamente com um código de status HTTP adequado (ex., [[yii\web\NotFoundHttpException]] representa um código de status 404). O Yii enviará a resposta juntamente com o código e o texto do status HTTP correspondente. O Yii também incluirá a representação serializada da exceção no corpo da resposta. Por exemplo:
```
HTTP/1.1 404 Not Found
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
```
A lista a seguir descrimina os códigos de status HTTP que são usados pelo framework REST do Yii:
* `200`: OK. Tudo funcionou conforme o esperado;
* `201`: Um recurso foi criado com êxito em resposta a uma requisição `POST`. O cabeçalho `location` contém a URL que aponta para o recurso recém-criado;
* `204`: A requisição foi tratada com sucesso e a resposta não contém nenhum conteúdo no corpo (por exemplo uma requisição `DELETE`);
* `304`: O recurso não foi modificado. Você pode usar a versão em cache;
* `400`: Requisição malfeita. Isto pode ser causado por várias ações por parte do usuário, tais como o fornecimento de um JSON inválido no corpo da requisição, fornecendo parâmetros inválidos, etc;
* `401`: Falha de autenticação;
* `403`: O usuário autenticado não tem permissão para acessar o recurso da API solicitado;
* `404`: O recurso requisitado não existe;
* `405`: Método não permitido. Favor verificar o cabeçalho `Allow` para conhecer os métodos HTTP permitidos;
* `415`: Tipo de mídia não suportada. O número de versão ou o content type requisitado são inválidos;
* `422`: Falha na validação dos dados (na resposta a uma requisição `POST`, por exemplo). Por favor, verifique o corpo da resposta para visualizar a mensagem detalhada do erro;
* `429`: Excesso de requisições. A requisição foi rejeitada devido a limitação de taxa;
* `500`: Erro interno do servidor. Isto pode ser causado por erros internos do programa.
## Customizando Resposta de Erro<span id="customizing-error-response"></span>
Às vezes você pode querer personalizar o formato de resposta de erro padrão. Por exemplo, em vez de confiar em usar diferentes status HTTP para indicar os diversos erros, você pode querer usar sempre o status 200 como resposta e colocar o código de status real como parte da estrutura JSON da resposta, como mostrado abaixo,
```
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"success": false,
"data": {
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
}
```
Para atingir este objetivo, você pode responder o evento `beforeSend` do componente `response` na configuração da aplicação:
```php
return [
// ...
'components' => [
'response' => [
'class' => 'yii\web\Response',
'on beforeSend' => function ($event) {
$response = $event->sender;
if ($response->data !== null && Yii::$app->request->get('suppress_response_code')) {
$response->data = [
'success' => $response->isSuccessful,
'data' => $response->data,
];
$response->statusCode = 200;
}
},
],
],
];
```
O código acima formatará a resposta (para ambas as respostas, bem-sucedidas e com falha) como explicado quando `suppress_response_code` é passado como um parâmetro `GET`.

193
docs/guide-pt-BR/rest-quick-start.md

@ -1,193 +0,0 @@
Introdução
===========
O Yii fornece um conjunto de ferramentas para simplificar a tarefa de implementar APIs RESTful Web Service. Em particular, o Yii suporta os seguintes recursos sobre APIs RESTful:
* Prototipagem rápida com suporte para APIs comuns de [Active Record](db-active-record.md);
* Negociação de formato do Response (suporte JSON e XML por padrão);
* Serialização de objeto configurável com suporte a campos de saída selecionáveis;
* Formatação adequada para a coleção e dados e validação de erros;
* Suporte a [HATEOAS](http://en.wikipedia.org/wiki/HATEOAS);
* Roteamento eficiente com verificação dos verbs (métodos) HTTP;
* Construído com suporte aos métodos `OPTIONS` e `HEAD`;
* Autenticação e autorização;
* Data caching e HTTP caching;
* Limitação de taxa;
Abaixo, utilizamos um exemplo para ilustrar como você pode construir um conjunto de APIs RESTful com um mínimo de codificação.
Suponha que você deseja expor os dados do usuário via APIs RESTful. Os dados do usuário estão guardados na tabela `user` e você já criou a classe [active record](db-active-record.md) `app\models\User` para acessar os dados do usuário.
## Criando um Controller (Controlador) <span id="creating-controller"></span>
Primeiramente, crie uma classe [controller](structure-controllers.md) `app\controllers\UserController` como a seguir,
```php
namespace app\controllers;
use yii\rest\ActiveController;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
}
```
A classe controller estende de [[yii\rest\ActiveController]], que implementa um conjunto comum de ações RESTful. Especificando [[yii\rest\ActiveController::modelClass|modelClass]]
como `app\models\User`, o controller sabe qual o model que pode ser usado para a recuperação e manipulação de dados.
## Configurando Regras de URL <span id="configuring-url-rules"></span>
Em seguida, modifique a configuração do componente `urlManager` na configuração da aplicação:
```php
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
],
]
```
A configuração acima primeiramente adiciona uma regra de URL para o controller `user` de modo que os dados do usuário podem ser acessados e manipulados com URLs amigáveis e métodos HTTP significativos.
## Ativando o Input via JSON <span id="enabling-json-input"></span>
Para fazer a API aceitar dados no formato JSON, configure a propriedade [[yii\web\Request::$parsers|parsers]] do [componente de aplicação](structure-application-components.md) `request` para usar o [[yii\web\JsonParser]] para realizar input via JSON:
```php
'request' => [
'parsers' => [
'application/json' => 'yii\web\JsonParser',
]
]
```
> Observação: A configuração acima é opcional. Sem esta configuração, a API só iria reconhecer os formatos de input `application/x-www-form-urlencoded` e `multipart/form-data`.
## Testando <span id="trying-it-out"></span>
Com o mínimo de esforço acima, você já terminou sua tarefa de criar as APIs RESTful para acessar os dados do usuário. As APIs que você criou incluem:
* `GET /users`: listar todos os usuários página por página;
* `HEAD /users`: mostrar a informações gerais da listagem de usuários;
* `POST /users`: criar um novo usuário;
* `GET /users/123`: retorna detalhes do usuário 123;
* `HEAD /users/123`: mostra informações gerais do usuário 123;
* `PATCH /users/123` e `PUT /users/123`: atualiza o usuário 123;
* `DELETE /users/123`: deleta o usuário 123;
* `OPTIONS /users`: mostra os métodos suportados em relação à URL `/users`;
* `OPTIONS /users/123`: mostra os métodos suportados em relação à URL `/users/123`.
> Observação: O Yii vai pluralizar automaticamente nomes de controllers para uso em URLs (também chamadas *endpoints*).
> Você pode configurar isso usando a propriedade [[yii\rest\UrlRule::$pluralize]].
Você pode acessar suas APIs com o comando `curl` mostrado abaixo,
```
$ curl -i -H "Accept:application/json" "http://localhost/users"
HTTP/1.1 200 OK
...
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
[
{
"id": 1,
...
},
{
"id": 2,
...
},
...
]
```
Tente alterar o tipo de conteúdo para `application/xml` e você vai ver o resultado retornado em formato XML:
```
$ curl -i -H "Accept:application/xml" "http://localhost/users"
HTTP/1.1 200 OK
...
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/xml
<?xml version="1.0" encoding="UTF-8"?>
<response>
<item>
<id>1</id>
...
</item>
<item>
<id>2</id>
...
</item>
...
</response>
```
O seguinte comando irá criar um novo usuário, enviando uma solicitação POST com os dados do usuário em formato JSON:
```
$ curl -i -H "Accept:application/json" -H "Content-Type:application/json" -XPOST "http://localhost/users" -d '{"username": "example", "email": "user@example.com"}'
HTTP/1.1 201 Created
...
Location: http://localhost/users/1
Content-Length: 99
Content-Type: application/json; charset=UTF-8
{"id":1,"username":"example","email":"user@example.com","created_at":1414674789,"updated_at":1414674789}
```
> Dica: Você também pode acessar suas APIs via navegador, digitando a URL `http://localhost/users`. No entanto, você pode precisar de alguns plugins do navegador para enviar cabeçalhos de solicitações específicas.
Como você pode ver, no cabeçalho da resposta, há informações sobre a contagem total, número de páginas, etc. Há também links que permitem navegar para outras páginas de dados. Por exemplo, `http://localhost/users?page=2` lhe daria a próxima página dos dados de usuário.
Usando os parâmetros `fields` e `expand`, você também pode especificar os campos que devem ser incluídos no resultado. Por exemplo, a URL `http://localhost/users?fields=id,email` só retornará os campos `id` e `email`.
> Observação: Você deve ter notado que o resultado de `http://localhost/users`
> inclui alguns campos confidenciais,
> Tal como `password_hash`, `auth_key`. Você certamente não quer que
> eles apareçam no resultado da sua API.
> Você pode e deve filtrar esses campos, conforme descrito na seção
> [Response Formatting](rest-response-formatting.md).
## Resumo <span id="summary"></span>
Usando o framework API RESTful do Yii, você implementa uma URL desses campos, conforme descrito na seção de ações do controller, um controller para organizar as ações que implementam as URLs para um único tipo de recurso.
Os recursos são representados como modelos de dados, que se estendem a partir da classe [[yii\base\Model]]. Se você estiver trabalhando com bancos de dados (relacional ou NoSQL), é recomendado que você use [[yii\db\ActiveRecord|ActiveRecord]] para representar recursos.
Você pode usar [[yii\rest\UrlRule]] para simplificar o roteamento para suas URLs da API.
Embora não seja exigido, é recomendável que você desenvolva suas APIs RESTful como uma aplicação separada, diferente do seu frontend e backend para facilitar a manutenção.

38
docs/guide-pt-BR/rest-rate-limiting.md

@ -1,38 +0,0 @@
Limitador de Acesso
=============
Para prevenir abusos, você pode considerar a utilização de um *limitador de acesso* nas suas APIs. Por exemplo, você pode querer limitar o uso da API para cada usuário em no máximo 100 chamadas a cada 10 minutos. Se o número de solicitações recebidas por usuário ultrapassar este limite, uma resposta com status 429 (significa "Muitas Requisições") deve ser retornada.
Para habilitar o limitador de acesso, a [[yii\web\User::identityClass|classe de identidade do usuário]] deve implementar [[yii\filters\RateLimitInterface]]. Esta interface requer a implementação de três métodos:
* `getRateLimit()`: retorna o número máximo de pedidos permitidos e o período de tempo (ex., `[100, 600]` significa que pode haver, no máximo, 100 chamadas de API dentro de 600 segundo);
* `loadAllowance()`: retorna o número restante de pedidos permitidos e a hora da última verificação;
* `saveAllowance()`: salva tanto o número restante de requisições e a hora atual.
Você pode usar duas colunas na tabela de usuários para registrar estas informações. Com esses campos definidos, então `loadAllowance()` e `saveAllowance()` podem ser implementados para ler e guardar os valores das duas colunas correspondentes ao atual usuário autenticado.
Para melhorar o desempenho, você também pode considerar armazenar essas informações em um cache ou armazenamento NoSQL.
Uma vez que a classe de identidade do usuário estiver com a interface necessária implementada, o Yii automaticamente usará a classe [[yii\filters\RateLimiter]] configurada como um filtro da ação para o [[yii\rest\Controller]] realizar a verificação da limitação do acesso. O limitador de acesso lançará uma exceção [[yii\web\TooManyRequestsHttpException]] quando o limite for excedido.
Você pode configurar o limitador de acesso da seguinte forma em suas classes controller REST:
```php
public function behaviors()
{
$behaviors =
parent::behaviors();
$behaviors['rateLimiter']['enableRateLimitHeaders']
= false;
return $behaviors;
}
```
Quando o limitador de acesso está habilitado, por padrão a cada resposta será enviada com o seguinte cabeçalho HTTP contendo a informação da atual taxa de limitação:
* `X-Rate-Limit-Limit`, o número máximo permitido de pedidos em um período de tempo;
* `X-Rate-Limit-Remaining`, o número de pedidos restantes no período de tempo atual;
* `X-Rate-Limit-Reset`, o número de segundos de espera a fim de obter o número máximo de pedidos permitidos.
Você pode desativar esses cabeçalhos, configurando [[yii\filters\RateLimiter::enableRateLimitHeaders]] para `false`, como mostrado no exemplo acima.

192
docs/guide-pt-BR/rest-resources.md

@ -1,192 +0,0 @@
Recursos
=========
APIs RESTful tratam de como acessar e manipular *recursos*. Você pode ver recursos como [models](structure-models.md) no paradigma MVC.
Embora não haja restrição na forma de representar um recurso, no Yii você normalmente representaria recursos como objetos de [[yii\base\Model]] ou de uma classe filha (ex. [[yii\db\ActiveRecord]]), pelas seguintes razões:
* [[yii\base\Model]] implementa a interface [[yii\base\Arrayable]], que permite que você personalize como você deseja expor dados de recursos através das APIs RESTful.
* [[yii\base\Model]] suporta [validação de dados de entrada](input-validation.md), que é importante se as suas APIs RESTful precisarem suportar entrada de dados.
* [[yii\db\ActiveRecord]] fornece acesso poderoso a banco de dados com suporte a manipulação dos dados, o que o torna um ajuste perfeito se seus dados de recursos estiverem armazenado em bases de dados.
Nesta seção, vamos principalmente descrever como uma classe de recurso que se estende de [[yii\base\Model]] (ou alguma classe filha) pode especificar quais os dados podem ser retornados via APIs RESTful. Se a classe de recurso não estender de [[yii\base\Model]], então todas as suas variáveis públicas serão retornadas.
## Campos <span id="fields"></span>
Ao incluir um recurso em uma resposta da API RESTful, o recurso precisa ser serializado em uma string. O Yii quebra este processo em duas etapas. Primeiro, o recurso é convertido em um array utilizando [[yii\rest\Serializer]]. Por último, o array é serializado em uma string no formato solicitado (ex. JSON, XML) através do [[yii\web\ResponseFormatterInterface|response formatters]]. O primeiro passo é o que você deve centrar-se principalmente no desenvolvimento de uma classe de recurso.
Sobrescrevendo [[yii\base\Model::fields()|fields()]] e/ou [[yii\base\Model::extraFields()|extraFields()]], você pode especificar quais os dados, chamados *fields*, no recurso podem ser colocados no array.
A diferença entre estes dois métodos é que o primeiro especifica o conjunto padrão de campos que devem ser incluídos no array, enquanto que o último especifica campos adicionais que podem ser incluídos no array, se um usuário final solicitá-los via o parâmetro de pesquisa `expand`. Por exemplo:
```
// retorna todos os campos declarados em fields()
http://localhost/users
// retorna apenas os campos id e email, desde que estejam declarados em fields()
http://localhost/users?fields=id,email
// retorna todos os campos de fields() e o campo profile se este estiver no extraFields()
http://localhost/users?expand=profile
// retorna apenas o campo id, email e profile, desde que estejam em fields() e extraFields()
http://localhost/users?fields=id,email&expand=profile
```
### Sobrescrevendo `fields()` <span id="overriding-fields"></span>
Por padrão, [[yii\base\Model::fields()]] retorna todos os atributos do model como campos, enquanto [[yii\db\ActiveRecord::fields()]] só retorna os atributos que tenham sido preenchidos a partir do DB.
Você pode sobrescrever `fields()` para adicionar, remover, renomear ou redefinir campos. O valor do retorno de `fields()` deve ser um array. As chaves do array são os nomes dos campos e os valores são as definições dos campos correspondentes, que podem ser tanto nomes de propriedade/atributo ou funções anônimas retornando o valor do campo correspondente. No caso especial de um nome de um campo for o mesmo que sua definição de nome de atributo, você pode omitir a chave do array. Por exemplo:
```php
// explicitamente lista todos os campos,
// melhor usado quando você quer ter certeza de que as alterações
// na sua tabela ou atributo do model não causaram alterações
// nos seus campos (Manter compatibilidade da API).
public function fields()
{
return [
// Nome do campo é igual ao nome do atributo
'id',
// nome do campo é "email", o nome do atributo correspondente é "email_address"
'email' => 'email_address',
// nome do campo é "name", seu valor é definido por um PHP callback
'name' => function ($model) {
return $model->first_name . ' ' . $model->last_name;
},
];
}
// filtrar alguns campos, melhor usado quando você deseja herdar a implementação do pai
// e deseja esconder alguns campos confidenciais.
public function fields()
{
$fields = parent::fields();
// remove campos que contém informações confidenciais
unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']);
return $fields;
}
```
> Aviso: Como o padrão é ter todos os atributos de um model incluídos
> no resultados da API, você deve examinar os seus dados para certificar-se de que
> eles não contenham informações confidenciais.
> Se existirem tais informações, você deve sobrescrever `fields()` para filtrá-los.
> No exemplo acima, nós escolhemos filtrar `auth_key`,
> `password_hash` e `password_reset_token`.
### Sobrescrevendo `extraFields()` <span id="overriding-extra-fields"></span>
Por padrão, o [[yii\base\Model::extraFields()]] não retorna nada, enquanto o [[yii\db\ActiveRecord::extraFields()]] retorna os nomes das relações que foram populadas a partir do DB.
O formato do retorno dos dados do `extraFields()` é o mesmo de `fields()`. Geralmente, `extraFields()` é mais usado para especificar os campos cujos valores são objetos. Por exemplo, dada a seguinte declaração de campo,
```php
public function fields()
{
return ['id', 'email'];
}
public function extraFields()
{
return ['profile'];
}
```
o request com `http://localhost/users?fields=id,email&expand=profile` pode retornar o seguinte dados em formato JSON:
```php
[
{
"id": 100,
"email": "100@example.com",
"profile": {
"id": 100,
"age": 30,
}
},
...
]
```
## Links <span id="links"></span>
[HATEOAS](http://en.wikipedia.org/wiki/HATEOAS) é uma abreviação de “Hypermedia as the Engine of Application State”, que promove as APIs Restfull retornarem informações para permitir aos clientes descobrirem quais ações são suportadas pelos recursos retornados. O sentido de HATEOAS é retornar um conjunto de hiperlinks em relação às informações quando os recursos de dados são servidos pelas APIs.
Suas classes de recursos podem suportar HATEOAS implementando a interface [[yii\web\Linkable]]. Esta interface contém um único método [[yii\web\Linkable::getLinks()|getLinks()]] que deve retornar uma lista de [[yii\web\Link|links]].
Tipicamente, você deve retornar pelo menos o link `self` representando a URL para o mesmo objeto de recurso. Por exemplo:
```php
use yii\db\ActiveRecord;
use yii\web\Link;
use yii\web\Linkable;
use yii\helpers\Url;
class User extends ActiveRecord implements Linkable
{
public function getLinks()
{
return [
Link::REL_SELF => Url::to(['user/view', 'id' => $this->id], true),
];
}
}
```
Quando o objeto `User` for retornado em uma resposta, será composto de um elemento `_links` representando os links relacionados ao *user*, por exemplo:
```
{
"id": 100,
"email": "user@example.com",
// ...
"_links" => {
"self": {
"href": "https://example.com/users/100"
}
}
}
```
## Collections (Coleções) <span id="collections"></span>
Objetos de recursos podem ser agrupados em *collections*. Cada collection contém uma lista de objetos de recurso do mesmo tipo.
Embora os collections podem ser representados como arrays, normalmente, é preferível representá-los como [data providers](output-data-providers.md). Isto porque data providers suportam ordenação e paginação de recursos, que é um recurso comumente necessário para APIs RESTful retornarem collections. Por exemplo, ação a seguir retorna um data provider sobre o recurso *post*:
```php
namespace app\controllers;
use yii\rest\Controller;
use yii\data\ActiveDataProvider;
use app\models\Post;
class PostController extends Controller
{
public function actionIndex()
{
return new ActiveDataProvider([
'query' => Post::find(),
]);
}
}
```
Quando um data provider está enviando uma resposta com a API RESTful, o [[yii\rest\Serializer]] pegará a página atual de recursos e a serializa como um array de objetos de recurso. Adicionalmente, o [[yii\rest\Serializer]] também incluirá as informações de paginação pelo seguinte cabeçalho HTTP:
* `X-Pagination-Total-Count`: O número total de recursos;
* `X-Pagination-Page-Count`: O número de páginas;
* `X-Pagination-Current-Page`: A página atual (a primeira página é 1);
* `X-Pagination-Per-Page`: O numero de recursos em cada página;
* `Link`: Um conjunto de links de navegação, permitindo que o cliente percorra os recursos página por página.
Um exemplo pode ser encontrado na seção [Introdução](rest-quick-start.md#trying-it-out).

139
docs/guide-pt-BR/rest-response-formatting.md

@ -1,139 +0,0 @@
Formatando Respostas
===================
Ao manipular uma requisição da API RESTful, a aplicação normalmente realiza as seguintes etapas que estão relacionadas com a formatação da resposta:
1. Determinar diversos fatores que podem afetar o formato da resposta, tais como tipo de mídia, idioma, versão, etc. Este processo também é conhecido como [negociação de conteúdo (*content negotiation*)](http://en.wikipedia.org/wiki/Content_negotiation).
2. Converter objetos de recursos em arrays, como descrito na seção [Recursos](rest-resources.md). Isto é feito por [[yii\rest\Serializer]].
3. Converte arrays em uma string no formato como determinado pela etapa de negociação de conteúdo. Isto é feito pelos [[yii\web\ResponseFormatterInterface|formatadores de respostas]] registrados na propriedade [[yii\web\Response::formatters|formatters]] do [componente de aplicação](structure-application-components.md) `response`.
## Negociação de Conteúdo <span id="content-negotiation"></span>
O Yii suporta a negociação de conteúdo através do filtro [[yii\filters\ContentNegotiator]]. A classe base de controller API RESTful [[yii\rest\Controller]] está equipado com este filtro sob o nome de `contentNegotiator`. O filtro fornece negociação de formato de resposta, bem como negociação de idioma. Por exemplo, se uma requisição da API RESTful tiver o seguinte cabeçalho,
```
Accept: application/json; q=1.0, */*; q=0.1
```
ele obterá uma resposta em formato JSON, como o seguinte:
```
$ curl -i -H "Accept: application/json; q=1.0, */*; q=0.1" "http://localhost/users"
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
[
{
"id": 1,
...
},
{
"id": 2,
...
},
...
]
```
Por baixo dos panos, antes de uma ação do controlador API RESTful ser executada, o filtro [[yii\filters\ContentNegotiator]] verificará o `Accept` do cabeçalho HTTP na requisição e definirá o [[yii\web\Response::format|response format]] para `'json'`. Após a ação ser executada e retornar o objeto resultante de recursos ou coleção, [[yii\rest\Serializer]] converterá o resultado em um array. E finalmente, [[yii\web\JsonResponseFormatter]] irá serializar o array em uma string JSON e incluí-la no corpo da resposta.
Por padrão, APIs RESTful suportam tanto os formatos JSON quanto XML. Para suportar um novo formato, você deve configurar a propriedade [[yii\filters\ContentNegotiator::formats|formats]] do filtro `contentNegotiator` como mostrado no exemplo a seguir em suas classes do controlador da API:
```php
use yii\web\Response;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_HTML;
return $behaviors;
}
```
As chaves da propriedade `formats` são os tipos MIME suportados, enquanto os valores são os nomes de formato de resposta correspondentes que devem ser suportados em
[[yii\web\Response::formatters]].
## Serializando Dados <span id="data-serializing"></span>
Como foi descrito acima, [[yii\rest\Serializer]] é a peça central responsável pela conversão de objetos de recursos ou coleções em arrays. Ele reconhece objetos que implementam a interface [[yii\base\ArrayableInterface]] bem como [[yii\data\DataProviderInterface]]. O primeiro é aplicado principalmente pelos objetos de recursos, enquanto o último se aplica mais a coleções de recursos.
Você pode configurar o serializador, definindo a propriedade [[yii\rest\Controller::serializer]] com um array de configuração.
Por exemplo, às vezes você pode querer ajudar a simplificar o trabalho de desenvolvimento do cliente, incluindo informações de paginação diretamente no corpo da resposta. Para fazê-lo, configure a propriedade [[yii\rest\Serializer::collectionEnvelope]] como a seguir:
```php
use yii\rest\ActiveController;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
public $serializer = [
'class' => 'yii\rest\Serializer',
'collectionEnvelope' => 'items',
];
}
```
Você pode, então, obter a seguinte resposta para a url `http://localhost/users`:
```
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"items": [
{
"id": 1,
...
},
{
"id": 2,
...
},
...
],
"_links": {
"self": {
"href": "http://localhost/users?page=1"
},
"next": {
"href": "http://localhost/users?page=2"
},
"last": {
"href": "http://localhost/users?page=50"
}
},
"_meta": {
"totalCount": 1000,
"pageCount": 50,
"currentPage": 1,
"perPage": 20
}
}
```

85
docs/guide-pt-BR/rest-routing.md

@ -1,85 +0,0 @@
Roteamento
=======
Com as classes de recurso e controller prontas, você pode acessar os recursos utilizando uma URL como `http://localhost/index.php?r=user/create`, semelhante ao que você pode fazer com aplicações Web normais.
Na prática, normalmente você desejará utilizar URLs amigáveis e tirar proveito dos métodos HTTP.
Por exemplo, uma requisição `POST /users` seria o mesmo que a ação `user/create`.
Isto pode ser feito facilmente através da configuração do [componente de aplicação](structure-application-components.md) `urlManager` conforme mostrado a seguir:
```php
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
],
]
```
Em comparação com o gerenciamento de URL para aplicações Web, a principal novidade acima é o uso de [[yii\rest\UrlRule]] para rotear requisições API RESTful. Esta classe especial criará um conjunto de regras de URL filhas para dar suporte ao roteamento e a criação de URL para o controller especificado.
Por exemplo, o código acima é mais ou menos equivalente às seguintes regras:
```php
[
'PUT,PATCH users/<id>' => 'user/update',
'DELETE users/<id>' => 'user/delete',
'GET,HEAD users/<id>' => 'user/view',
'POST users' => 'user/create',
'GET,HEAD users' => 'user/index',
'users/<id>' => 'user/options',
'users' => 'user/options',
]
```
E as seguintes URLs (também chamadas de *endpoints*) da API são suportados por esta regra:
* `GET /users`: lista todos os usuários página por página;
* `HEAD /users`: mostrar a informações gerais da listagem de usuários;
* `POST /users`: cria um novo usuário;
* `GET /users/123`: retorna detalhes do usuário 123;
* `HEAD /users/123`: mostrar a informações gerais do usuário 123;
* `PATCH /users/123` and `PUT /users/123`: atualiza o usuário 123;
* `DELETE /users/123`: deleta o usuário 123;
* `OPTIONS /users`: exibe os métodos suportados pela URL `/users`;
* `OPTIONS /users/123`: exibe os métodos suportados pela URL `/users/123`.
Você pode configurar as opções `only` e `except` para listar explicitamente quais ações são suportadas ou quais ações devem ser desativadas, respectivamente. Por exemplo,
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'except' => ['delete', 'create', 'update'],
],
```
Você também pode configurar `patterns` ou `extraPatterns` para redefinir padrões existentes ou adicionar novos padrões suportados por esta regra. Por exemplo, para acessar a uma nova ação `search` pela URL `GET /users/search`, configure a opção `extraPatterns` como a seguir,
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'extraPatterns' => [
'GET search' => 'search',
],
]
```
Você deve ter notado que o ID `user` de controller aparece no plural como `users` na extremidade das URLs. Isto acontece porque [[yii\rest\UrlRule]] pluraliza os IDs de controllers automaticamente na criação de regras de URLs filhas.
Você pode desabilitar este comportamento configurando [[yii\rest\UrlRule::pluralize]] para `false`.
> Observação: A pluralização dos IDs de controllers são feitas pelo método [[yii\helpers\Inflector::pluralize()]]. O método respeita as regras especiais de pluralização. Por exemplo, a palavra `box` será pluralizada para `boxes` em vez de `boxs`.
Caso a pluralização automática não encontre uma opção para a palavra requerida, você pode configurar a propriedade [[yii\rest\UrlRule::controller]] para especificar explicitamente como mapear um nome para ser usado como uma URL para um ID de controller. Por exemplo, o seguinte código mapeia o nome `u` para o ID `user` de controller.
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => ['u' => 'user'],
]
```

94
docs/guide-pt-BR/rest-versioning.md

@ -1,94 +0,0 @@
Versionamento
==========
Uma boa API é *versionada*: Mudanças e novos recursos são implementados em novas versões da API em vez de alterar continuamente apenas uma versão. Diferente de aplicações Web, com a qual você tem total controle do código de ambos os lados cliente e servidor, APIs são destinadas a ser utilizadas por clientes além de seu controle. Por esta razão, a compatibilidade (BC) entre as APIs deve ser mantida sempre que possível. Se uma mudança que pode quebrar esta compatibilidade é necessária, você deve introduzi-la em uma nova versão de API e subir o número da versão. Os clientes existentes podem continuar a usar a versão antiga da API; e os clientes novos ou atualizados podem obter a nova funcionalidade na nova versão da API.
> Dica: Consulte o artigo [Semantic Versioning](http://semver.org/) para obter mais informações sobre como projetar números de versão da API.
Uma maneira comum de implementar versionamento de API é incorporar o número da versão nas URLs da API. Por exemplo, `http://example.com/v1/users` representa o terminal `/users` da API versão 1.
Outro método de versionamento de API, que tem sido muito utilizado recentemente, é colocar o número da versão nos cabeçalhos das requisições HTTP. Isto é tipicamente feito através do cabeçalho `Accept`:
```
// Através de um parâmetro
Accept: application/json; version=v1
// através de um vendor content type
Accept: application/vnd.company.myapp-v1+json
```
Ambos os métodos tem seus prós e contras, e há uma série de debates sobre cada abordagem. A seguir, você verá uma estratégia prática para o controle de versão de API que é uma mistura dos dois métodos:
* Coloque cada versão principal de implementação da API em um módulo separado cuja identificação é o número de versão principal (ex. `v1`, `v2`). Naturalmente, as URLs da API irão conter os números da versão principal.
* Dentro de cada versão principal (e, assim, dentro do módulo correspondente), utilize o cabeçalho `Accept` da requisição HTTP para determinar o número de versão secundária e escrever código condicional para responder às versões menores em conformidade.
Para cada módulo destinado a uma versão principal, deve incluir o recurso e a classe de controller destinados a esta versão específica.
Para melhor separar a responsabilidade do código, você pode manter um conjunto comum de classes base de recursos e de controller e criar subclasses delas para cada versão individual do módulo. Dentro das subclasses, implementar o código concreto, tais como `Model::fields()`.
Seu código pode ser organizado da seguinte maneira:
```
api/
common/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
modules/
v1/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
Module.php
v2/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
Module.php
```
A configuração da sua aplicação seria algo como:
```php
return [
'modules' => [
'v1' => [
'class' => 'app\modules\v1\Module',
],
'v2' => [
'class' => 'app\modules\v2\Module',
],
],
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => ['v1/user', 'v1/post']],
['class' => 'yii\rest\UrlRule', 'controller' => ['v2/user', 'v2/post']],
],
],
],
];
```
Como resultado do código acima, `http://example.com/v1/users` retornará a lista de usuários na versão 1, enquanto `http://example.com/v2/users` retornará a lista de usuários na versão 2.
Graças aos módulos, o código para diferentes versões principais pode ser bem isolado. Entretanto esta abordagem torna possível a reutilização de código entre os módulos através de classes bases comuns e outros recursos partilhados.
Para lidar com números de subversões, você pode tirar proveito da negociação de conteúdo oferecida pelo behavior [[yii\filters\ContentNegotiator|contentNegotiator]]. O behavior `contentNegotiator` irá configurar a propriedade [[yii\web\Response::acceptParams]] que determinará qual versão é suportada.
Por exemplo, se uma requisição é enviada com o cabeçalho HTTP `Accept: application/json; version=v1`, Após a negociação de conteúdo, [[yii\web\Response::acceptParams]] terá o valor `['version' => 'v1']`.
Com base na informação da versão em `acceptParams`, você pode escrever um código condicional em lugares tais como ações, classes de recursos, serializadores, etc. para fornecer a funcionalidade apropriada.
Uma vez que subversões por definição devem manter compatibilidades entre si, esperamos que não haja muitas verificações de versão em seu código. De outra forma, você pode precisar criar uma nova versão principal.

14
docs/guide-ru/README.md

@ -128,20 +128,6 @@ All Rights Reserved.
* [HTTP кэширование](caching-http.md)
Веб-сервисы REST
----------------
* [Быстрый старт](rest-quick-start.md)
* [Ресурсы](rest-resources.md)
* [Контроллеры](rest-controllers.md)
* [Роутинг](rest-routing.md)
* [Форматирование ответа](rest-response-formatting.md)
* [Аутентификация](rest-authentication.md)
* [Ограничение частоты запросов](rest-rate-limiting.md)
* [Версионирование](rest-versioning.md)
* [Обработка ошибок](rest-error-handling.md)
Инструменты разработчика
------------------------

126
docs/guide-ru/rest-authentication.md

@ -1,126 +0,0 @@
Аутентификация
==============
В отличие от Web-приложений, RESTful API обычно не сохраняют информацию о состоянии, а это означает, что сессии и куки
использовать не следует. Следовательно, раз состояние аутентификации пользователя не может быть сохранено в сессиях или куках,
каждый запрос должен приходить вместе с определенным видом параметров аутентификации. Общепринятая практика состоит в том,
что для аутентификации пользователя с каждым запросом отправляется секретный токен доступа. Так как токен доступа
может использоваться для уникальной идентификации и аутентификации пользователя, **запросы к API всегда должны отсылаться
через протокол HTTPS, чтобы предотвратить атаки «человек посередине» (англ. "man-in-the-middle", MitM)**.
Есть различные способы отправки токена доступа:
* [HTTP Basic Auth](http://en.wikipedia.org/wiki/Basic_access_authentication): токен доступа
отправляется как имя пользователя. Такой подход следует использовать только в том случае, когда токен доступа может быть безопасно сохранен
на стороне абонента API. Например, если API используется программой, запущенной на сервере.
* Параметр запроса: токен доступа отправляется как параметр запроса в URL-адресе API, т.е. примерно таким образом:
`https://example.com/users?access-token=xxxxxxxx`. Так как большинство Web-серверов сохраняют параметры запроса в своих логах,
такой подход следует применять только при работе с `JSONP`-запросами, которые не могут отправлять токены доступа
в HTTP-заголовках.
* [OAuth 2](http://oauth.net/2/): токен доступа выдается абоненту API сервером авторизации
и отправляется API-серверу через [HTTP Bearer Tokens](http://tools.ietf.org/html/rfc6750),
в соответствии с протоколом OAuth2.
Yii поддерживает все выше перечисленные методы аутентификации. Вы также можете легко создавать новые методы аутентификации.
Чтобы включить аутентификацию для ваших API, выполните следующие шаги:
1. У [компонента приложения](structure-application-components.md) `user` установите свойство
[[yii\web\User::enableSession|enableSession]] равным `false`.
2. Укажите, какие методы аутентификации вы планируете использовать, настроив поведение `authenticator`
в ваших классах REST-контроллеров.
3. Реализуйте метод [[yii\web\IdentityInterface::findIdentityByAccessToken()]] в вашем [[yii\web\User::identityClass|классе UserIdentity]].
Шаг 1 не обязателен, но рекомендуется его всё-таки выполнить, так как RESTful API не должен сохранять информацию о
состоянии клиента. Когда свойство [[yii\web\User::enableSession|enableSession]] установлено в `false`, состояние
аутентификации пользователя НЕ БУДЕТ сохраняться между запросами с использованием сессий. Вместо этого аутентификация
будет выполняться для каждого запроса, что достигается шагами 2 и 3.
> Tip: если вы разрабатываете RESTful API в пределах приложения, вы можете настроить свойство
> [[yii\web\User::enableSession|enableSession]] компонента приложения `user` в конфигурации приложения. Если вы
> разрабатываете RESTful API как модуль, можете добавить следующую строчку в метод `init()` модуля:
> ```php
> public function init()
> {
> parent::init();
> \Yii::$app->user->enableSession = false;
> }
> ```
Например, для использования HTTP Basic Auth, вы можете настроить свойство `authenticator` следующим образом:
```php
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpBasicAuth::class,
];
return $behaviors;
}
```
Если вы хотите включить поддержку всех трёх описанных выше методов аутентификации, можете использовать `CompositeAuth`:
```php
use yii\filters\auth\CompositeAuth;
use yii\filters\auth\HttpBasicAuth;
use yii\filters\auth\HttpBearerAuth;
use yii\filters\auth\QueryParamAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => CompositeAuth::class,
'authMethods' => [
HttpBasicAuth::class,
HttpBearerAuth::class,
QueryParamAuth::class,
],
];
return $behaviors;
}
```
Каждый элемент в массиве `authMethods` должен быть названием класса метода аутентификации или массивом настроек.
Реализация метода `findIdentityByAccessToken()` определяется особенностями приложения. Например, в простом варианте,
когда у каждого пользователя есть только один токен доступа, вы можете хранить этот токен в поле `access_token`
таблицы пользователей. В этом случае метод `findIdentityByAccessToken()` может быть легко реализован в классе `User` следующим образом:
```php
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
class User extends ActiveRecord implements IdentityInterface
{
public static function findIdentityByAccessToken($token, $type = null)
{
return static::findOne(['access_token' => $token]);
}
}
```
После включения аутентификации описанным выше способом при каждом запросе к API запрашиваемый контроллер
будет пытаться аутентифицировать пользователя в своем методе `beforeAction()`.
Если аутентификация прошла успешно, контроллер выполнит другие проверки (ограничение частоты запросов, авторизация)
и затем выполнит действие. Информация об аутентифицированном пользователе может быть получена из объекта `Yii::$app->user->identity`.
Если аутентификация прошла неудачно, будет возвращен ответ с HTTP-кодом состояния 401 вместе с другими необходимыми заголовками
(такими, как заголовок `WWW-Authenticate` для HTTP Basic Auth).
## Авторизация <span id="authorization"></span>
После аутентификации пользователя вы, вероятно, захотите проверить, есть ли у него или у неё разрешение на выполнение запрошенного
действия с запрошенным ресурсом. Этот процесс называется *авторизацией* и подробно описан
в разделе «[Авторизация](security-authorization.md)».
Если ваши контроллеры унаследованы от [[yii\rest\ActiveController]], вы можете переопределить
метод [[yii\rest\Controller::checkAccess()|checkAccess()]] для выполнения авторизации. Этот метод будет вызываться
встроенными действиями, предоставляемыми контроллером [[yii\rest\ActiveController]].

157
docs/guide-ru/rest-controllers.md

@ -1,157 +0,0 @@
Контроллеры
===========
После создания классов ресурсов и настройки способа форматирования ресурсных данных следующим шагом
является создание действий контроллеров для предоставления ресурсов конечным пользователям через RESTful API.
В Yii есть два базовых класса контроллеров для упрощения вашей работы по созданию RESTful-действий:
[[yii\rest\Controller]] и [[yii\rest\ActiveController]]. Разница между этими двумя контроллерами в том,
что у последнего есть набор действий по умолчанию, который специально создан для работы с ресурсами,
представленными [Active Record](db-active-record.md). Так что если вы используете [Active Record](db-active-record.md)
и вас устраивает предоставленный набор встроенных действий, вы можете унаследовать классы ваших контроллеров
от [[yii\rest\ActiveController]], что позволит вам создать полноценные RESTful API, написав минимум кода.
[[yii\rest\Controller]] и [[yii\rest\ActiveController]] имеют следующие возможности, некоторые из которых
будут подробно описаны в следующих разделах:
* Проверка HTTP-метода;
* [Согласование содержимого и форматирование данных](rest-response-formatting.md);
* [Аутентификация](rest-authentication.md);
* [Ограничение частоты запросов](rest-rate-limiting.md).
[[yii\rest\ActiveController]], кроме того, предоставляет следующие возможности:
* Набор наиболее часто используемых действий: `index`, `view`, `create`, `update`, `delete` и `options`;
* Авторизация пользователя для запрашиваемых действия и ресурса.
## Создание классов контроллеров <span id="creating-controller"></span>
При создании нового класса контроллера в имени класса обычно используется
название типа ресурса в единственном числе. Например, контроллер, отвечающий за предоставление информации о пользователях,
можно назвать `UserController`.
Создание нового действия похоже на создание действия для Web-приложения. Единственное отличие в том,
что в RESTful-действиях вместо рендера результата в представлении с помощью вызова метода `render()`
вы просто возвращаете данные. Выполнение преобразования исходных данных в запрошенный формат ложится на
[[yii\rest\Controller::serializer|сериализатор]] и [[yii\web\Response|объект ответа]].
Например:
```php
public function actionView($id)
{
return User::findOne($id);
}
```
## Фильтры <span id="filters"></span>
Большинство возможностей RESTful API, предоставляемых [[yii\rest\Controller]], реализовано на основе [фильтров](structure-filters.md).
В частности, следующие фильтры будут выполняться в том порядке, в котором они перечислены:
* [[yii\filters\ContentNegotiator|contentNegotiator]]: обеспечивает согласование содержимого, более подробно описан
в разделе [Форматирование ответа](rest-response-formatting.md);
* [[yii\filters\VerbFilter|verbFilter]]: обеспечивает проверку HTTP-метода;
* [[yii\filters\auth\AuthMethod|authenticator]]: обеспечивает аутентификацию пользователя, более подробно описан
в разделе [Аутентификация](rest-authentication.md);
* [[yii\filters\RateLimiter|rateLimiter]]: обеспечивает ограничение частоты запросов, более подробно описан
в разделе [Ограничение частоты запросов](rest-rate-limiting.md).
Эти именованные фильтры объявлены в методе [[yii\rest\Controller::behaviors()|behaviors()]].
Вы можете переопределить этот метод для настройки отдельных фильтров, отключения каких-либо из них или для добавления
ваших собственных фильтров. Например, если вы хотите использовать только базовую HTTP-аутентификацию, вы можете
написать такой код:
```php
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpBasicAuth::class,
];
return $behaviors;
}
```
## Наследование от `ActiveController` <span id="extending-active-controller"></span>
Если ваш класс контроллера наследуется от [[yii\rest\ActiveController]], вам следует установить
значение его свойства [[yii\rest\ActiveController::modelClass|modelClass]] равным имени класса ресурса,
который вы планируете обслуживать с помощью этого контроллера. Класс ресурса должен быть унаследован от [[yii\db\ActiveRecord]].
### Настройка действий <span id="customizing-actions"></span>
По умолчанию [[yii\rest\ActiveController]] предоставляет набор из следующих действий:
* [[yii\rest\IndexAction|index]]: постраничный список ресурсов;
* [[yii\rest\ViewAction|view]]: возвращает подробную информацию об указанном ресурсе;
* [[yii\rest\CreateAction|create]]: создание нового ресурса;
* [[yii\rest\UpdateAction|update]]: обновление существующего ресурса;
* [[yii\rest\DeleteAction|delete]]: удаление указанного ресурса;
* [[yii\rest\OptionsAction|options]]: возвращает поддерживаемые HTTP-методы.
Все эти действия объявляются в методе [[yii\rest\ActiveController::actions()|actions()]].
Вы можете настроить эти действия или отключить какие-то из них, переопределив метод `actions()`, как показано ниже:
```php
public function actions()
{
$actions = parent::actions();
// отключить действия "delete" и "create"
unset($actions['delete'], $actions['create']);
// настроить подготовку провайдера данных с помощью метода "prepareDataProvider()"
$actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider'];
return $actions;
}
public function prepareDataProvider()
{
// подготовить и вернуть провайдер данных для действия "index"
}
```
Чтобы узнать, какие опции доступны для настройки классов отдельных действий, обратитесь к соответствующим разделам справочника классов.
### Выполнение контроля доступа <span id="performing-access-check"></span>
При предоставлении ресурсов через RESTful API часто бывает нужно проверять, имеет ли текущий пользователь разрешение
на доступ к запрошенному ресурсу (или ресурсам) и манипуляцию им (или ими). Для [[yii\rest\ActiveController]] эта задача
может быть решена переопределением метода [[yii\rest\ActiveController::checkAccess()|checkAccess()]] следующим образом:
```php
/**
* Проверяет права текущего пользователя.
*
* Этот метод должен быть переопределен, чтобы проверить, имеет ли текущий пользователь
* право выполнения указанного действия над указанной моделью данных.
* Если у пользователя нет доступа, следует выбросить исключение [[ForbiddenHttpException]].
*
* @param string $action ID действия, которое надо выполнить
* @param \yii\base\Model $model модель, к которой нужно получить доступ. Если `null`, это означает, что модель, к которой нужно получить доступ, отсутствует.
* @param array $params дополнительные параметры
* @throws ForbiddenHttpException если у пользователя нет доступа
*/
public function checkAccess($action, $model = null, $params = [])
{
// проверить, имеет ли пользователь доступ к $action и $model
// выбросить ForbiddenHttpException, если доступ следует запретить
if ($action === 'update' || $action === 'delete') {
if ($model->author_id !== \Yii::$app->user->id)
throw new \yii\web\ForbiddenHttpException(sprintf('You can only %s articles that you\'ve created.', $action));
}
}
```
Метод `checkAccess()` будет вызван действиями по умолчанию контроллера [[yii\rest\ActiveController]]. Если вы создаёте
новые действия и хотите в них выполнять контроль доступа, вы должны вызвать этот метод явно в своих новых действиях.
> Tip: вы можете реализовать метод `checkAccess()` с помощью ["Контроля доступа на основе ролей" (RBAC)](security-authorization.md).

92
docs/guide-ru/rest-error-handling.md

@ -1,92 +0,0 @@
Обработка ошибок
================
Если при обработке запроса к RESTful API в запросе пользователя обнаруживается ошибка или происходит
что-то непредвиденное на сервере, вы можете просто выбрасывать исключение, чтобы уведомить пользователя о нештатной ситуации.
Если же вы можете установить конкретную причину ошибки (например, запрошенный ресурс не существует), вам следует подумать
о том, чтобы выбрасывать исключение с соответствующим кодом состояния HTTP (например, [[yii\web\NotFoundHttpException]],
соответствующее коду состояния 404). Yii отправит ответ с соответствующим
HTTP-кодом и текстом. Он также включит в тело ответа сериализованное представление
исключения. Например:
```
HTTP/1.1 404 Not Found
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
```
Сводный список кодов состояния HTTP, используемых REST-фреймворком Yii:
* `200`: OK. Все сработало именно так, как и ожидалось.
* `201`: Ресурс был успешно создан в ответ на `POST`-запрос. Заголовок `Location`
содержит URL, указывающий на только что созданный ресурс.
* `204`: Запрос обработан успешно, и в ответе нет содержимого (для запроса `DELETE`, например).
* `304`: Ресурс не изменялся. Можно использовать закэшированную версию.
* `400`: Неверный запрос. Может быть связано с разнообразными проблемами на стороне пользователя, такими как неверные JSON-данные
в теле запроса, неправильные параметры действия, и т.д.
* `401`: Аутентификация завершилась неудачно.
* `403`: Аутентифицированному пользователю не разрешен доступ к указанной точке входа API.
* `404`: Запрошенный ресурс не существует.
* `405`: Метод не поддерживается. Сверьтесь со списком поддерживаемых HTTP-методов в заголовке `Allow`.
* `415`: Не поддерживаемый тип данных. Запрашивается неправильный тип данных или номер версии.
* `422`: Проверка данных завершилась неудачно (в ответе на `POST`-запрос, например). Подробные сообщения об ошибках смотрите в теле ответа.
* `429`: Слишком много запросов. Запрос отклонен из-за превышения ограничения частоты запросов.
* `500`: Внутренняя ошибка сервера. Возможная причина — ошибки в самой программе.
## Свой формат ответа с ошибкой <span id="customizing-error-response"></span>
Вам может понадобиться изменить формат ответа с ошибкой. Например, вместо использования разных статусов ответа HTTP
для разных ошибок, вы можете всегда отдавать статус 200, а реальный код статуса отдавать как часть JSON ответа:
```
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"success": false,
"data": {
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
}
```
Для этого можно использовать событие `beforeSend` компонента `response` прямо в конфигурации приложения:
```php
return [
// ...
'components' => [
'response' => [
'class' => 'yii\web\Response',
'on beforeSend' => function ($event) {
$response = $event->sender;
if ($response->data !== null && !empty(Yii::$app->request->get('suppress_response_code'))) {
$response->data = [
'success' => $response->isSuccessful,
'data' => $response->data,
];
$response->statusCode = 200;
}
},
],
],
];
```
Приведённый выше код изменит формат ответа (как для удачного запроса, так и для ошибок) если передан `GET`-параметр
`suppress_response_code`.

191
docs/guide-ru/rest-quick-start.md

@ -1,191 +0,0 @@
Быстрый старт
===========
Yii включает полноценный набор средств для упрощённой реализации [RESTful API](https://ru.wikipedia.org/wiki/REST).
В частности это следующие возможности:
* Быстрое создание прототипов с поддержкой распространенных API к [Active Record](db-active-record.md);
* Настройка формата ответа (JSON и XML реализованы по умолчанию);
* Получение сериализованных объектов с нужной вам выборкой полей;
* Надлежащее форматирование данных и ошибок при их валидации;
* Поддержка [HATEOAS](http://en.wikipedia.org/wiki/HATEOAS);
* Эффективная маршрутизация с надлежащей проверкой HTTP методов;
* Встроенная поддержка методов `OPTIONS` и `HEAD`;
* Аутентификация и авторизация;
* HTTP кэширование и кэширование данных;
* Настройка ограничения для частоты запросов (Rate limiting);
Рассмотрим пример, как можно настроить Yii под RESTful API, приложив при этом минимум усилий.
Предположим, вы захотели RESTful API для данных по пользователям. Эти данные хранятся в базе данных и для работы с ними
вами была ранее создана модель [[yii\db\ActiveRecord|ActiveRecord]] (класс `app\models\User`).
## Создание контроллера <span id="creating-controller"></span>
Во-первых, создадим класс контроллера `app\controllers\UserController`:
```php
namespace app\controllers;
use yii\rest\ActiveController;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
}
```
Класс контроллера наследуется от [[yii\rest\ActiveController]]. Мы задали [[yii\rest\ActiveController::modelClass|modelClass]]
как `app\models\User`, тем самым указав контроллеру, к какой модели ему необходимо обращаться для редактирования или
выборки данных.
## Настройка правил URL <span id="configuring-url-rules"></span>
Далее изменим настройки компонента `urlManager` в конфигурации приложения:
```php
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
],
]
```
Настройки выше добавляют правило для контроллера `user`, которое предоставляет доступ к данным пользователя через красивые
URL и логичные глаголы HTTP.
## Включение JSON на прием данных<span id="enabling-json-input"></span>
Для того чтобы API мог принимать данные в формате JSON, сконфигурируйте [[yii\web\Request::$parsers|parsers]] свойство у компонента `request` [application component](structure-application-components.md) на использование [[yii\web\JsonParser]] JSON данных на входе:
```php
'request' => [
'parsers' => [
'application/json' => 'yii\web\JsonParser',
]
]
```
> Note: Конфигурация, приведенная выше необязательна. Без приведенной выше конфигурации, API сможет определить только
`application/x-www-form-urlencoded` и `multipart/form-data` форматы.
## Пробуем <span id="trying-it-out"></span>
Вот так просто мы и создали RESTful API для доступа к данным пользователя. API нашего сервиса сейчас включает в себя:
* `GET /users`: получение постранично списка всех пользователей;
* `HEAD /users`: получение метаданных листинга пользователей;
* `POST /users`: создание нового пользователя;
* `GET /users/123`: получение информации по конкретному пользователю с id равным 123;
* `HEAD /users/123`: получение метаданных по конкретному пользователю с id равным 123;
* `PATCH /users/123` и `PUT /users/123`: изменение информации по пользователю с id равным 123;
* `DELETE /users/123`: удаление пользователя с id равным 123;
* `OPTIONS /users`: получение поддерживаемых методов, по которым можно обратится к `/users`;
* `OPTIONS /users/123`: получение поддерживаемых методов, по которым можно обратится к `/users/123`.
> Info: Yii автоматически использует множественное число от имени контроллера в URL.
Пробуем получить ответы по API используя `curl`:
```
$ curl -i -H "Accept:application/json" "http://localhost/users"
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
[
{
"id": 1,
...
},
{
"id": 2,
...
},
...
]
```
Попробуйте изменить заголовок допустимого формата ресурса на `application/xml`
и в ответ вы получите результат в формате XML:
```
$ curl -i -H "Accept:application/xml" "http://localhost/users"
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/xml
<?xml version="1.0" encoding="UTF-8"?>
<response>
<item>
<id>1</id>
...
</item>
<item>
<id>2</id>
...
</item>
...
</response>
```
> Tip: Вы можете получить доступ к API через веб-браузер, введя адрес `http://localhost/users`. Но в этом случае
для передачи определённых заголовков вам, скорее всего, потребуются дополнительные плагины для браузера.
Если внимательно посмотреть результат ответа, то можно обнаружить, что в заголовках есть информация об общем числе записей,
количестве страниц и т. д. Тут так же можно обнаружить ссылки на другие страницы, как, например,
`http://localhost/users?page=2`. Перейдя по ней можно получить вторую страницу данных пользователей.
Используя параметры `fields` и `expand` в URL, можно указать, какие поля должны быть включены в результат. Например,
по адресу `http://localhost/users?fields=id,email` мы получим информацию по пользователям, которая будет содержать
только `id` и `email`.
> Info: Вы наверное заметили, что при обращении к `http://localhost/users` мы получаем информацию с полями,
> которые нежелательно показывать, такими как `password_hash` и `auth_key`. Вы можете и должны отфильтровать их как
> описано в разделе «[Ресурсы](rest-resources.md)».
## Резюме <span id="summary"></span>
Используя Yii в качестве RESTful API фреймворка, мы реализуем точки входа API как действия контроллеров.
Контроллер используется для организации действий, которые относятся к определённому типу ресурса.
Ресурсы представлены в виде моделей данных, которые наследуются от класса [[yii\base\Model]].
Если необходима работа с базами данных (как с реляционными, так и с NoSQL), рекомендуется использовать для представления
ресурсов [[yii\db\ActiveRecord|ActiveRecord]].
Вы можете использовать [[yii\rest\UrlRule]] для упрощения маршрутизации точек входа API.
Хоть это не обязательно, рекомендуется отделять RESTful APIs приложение от основного веб-приложения. Такое разделение
легче обслуживается.

69
docs/guide-ru/rest-rate-limiting.md

@ -1,69 +0,0 @@
Ограничение частоты запросов
===============================
Чтобы избежать злоупотреблений, вам следует подумать о добавлении ограничения частоты запросов к вашим API. Например,
вы можете ограничить использование API до 100 вызовов в течение 10 минут для каждого пользователя. Если от пользователя
в течение этого периода времени приходит большее количество запросов, будет возвращаться ответ с кодом состояния 429
(«слишком много запросов»).
Чтобы включить ограничение частоты запросов, *[[yii\web\User::identityClass|класс user identity]]* должен реализовывать
интерфейс [[yii\filters\RateLimitInterface]]. Этот интерфейс требует реализации следующих трех методов:
* `getRateLimit()`: возвращает максимальное количество разрешенных запросов и период времени, например `[100, 600]`, что
означает не более 100 вызовов API в течение 600 секунд.
* `loadAllowance()`: возвращает оставшееся количество разрешенных запросов и *UNIX-timestamp* последней проверки
ограничения.
* `saveAllowance()`: сохраняет оставшееся количество разрешенных запросов и текущий *UNIX-timestamp*.
Вы можете использовать два столбца в таблице user для хранения количества разрешённых запросов и времени последней проверки.
В методах `loadAllowance()` и `saveAllowance()` можно реализовать чтение и сохранение значений этих столбцов в соответствии
с данными текущего аутентифицированного пользователя. Для улучшения производительности можно попробовать хранить эту
информацию в кэше или NoSQL хранилище.
Реализация в модели `User` может быть, например, такой:
```php
public function getRateLimit($request, $action)
{
return [$this->rateLimit, 1]; // $rateLimit запросов в секунду
}
public function loadAllowance($request, $action)
{
return [$this->allowance, $this->allowance_updated_at];
}
public function saveAllowance($request, $action, $allowance, $timestamp)
{
$this->allowance = $allowance;
$this->allowance_updated_at = $timestamp;
$this->save();
}
```
Как только соответствующий интерфейс будет реализован в классе identity, Yii начнёт автоматически проверять ограничения
частоты запросов при помощи [[yii\filters\RateLimiter]], фильтра действий для [[yii\rest\Controller]]. При превышении
ограничений будет выброшено исключение [[yii\web\TooManyRequestsHttpException]].
Вы можете настроить ограничитель частоты запросов в ваших классах REST-контроллеров следующим образом:
```php
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['rateLimiter']['enableRateLimitHeaders'] = false;
return $behaviors;
}
```
При включенном ограничении частоты запросов каждый ответ, по умолчанию, возвращается со следующими HTTP-заголовками,
содержащими информацию о текущих ограничениях:
* `X-Rate-Limit-Limit`: максимальное количество запросов, разрешённое в течение периода времени;
* `X-Rate-Limit-Remaining`: оставшееся количество разрешённых запросов в текущем периоде времени;
* `X-Rate-Limit-Reset`: количество секунд, которое нужно подождать до получения максимального количества разрешённых
запросов.
Вы можете отключить эти заголовки, установив свойство [[yii\filters\RateLimiter::enableRateLimitHeaders]] в `false`,
как показано в примере кода выше.

208
docs/guide-ru/rest-resources.md

@ -1,208 +0,0 @@
Ресурсы
=========
RESTful API строятся вокруг доступа к *ресурсам* и управления ими. Вы можете думать о ресурсах как
о [моделях](structure-models.md) из [MVC](http://ru.wikipedia.org/wiki/Model-View-Controller).
Хотя не существует никаких ограничений на то, как представить ресурс, в Yii ресурсы обычно представляются
как объекты [[yii\base\Model]] или дочерние классы (например [[yii\db\ActiveRecord]]), потому как:
* [[yii\base\Model]] реализует интерфейс [[yii\base\Arrayable]], который позволяет задать способ отдачи данных
ресурса через RESTful API.
* [[yii\base\Model]] поддерживает [валидацию](input-validation.md), что полезно для RESTful API реализующего ввод данных.
* [[yii\db\ActiveRecord]] даёт мощную поддержку работы с БД, что актуально если данные ресурса хранятся в ней.
В этом разделе, мы сосредоточимся на том, как при помощи класса ресурса, наследуемого от [[yii\base\Model]]
(или дочерних классов) задать какие данные будут возвращаться RESTful API. Если класс ресурса не наследуется от
[[yii\base\Model]], возвращаются всего его public свойства.
## Поля <span id="fields"></span>
Когда ресурс включается в ответ RESTful API, необходимо сериализовать его в строку. Yii разбивает этот процесс на два этапа.
Сначала ресурс конвертируется в массив при помощи [[yii\rest\Serializer]]. На втором этапе массив сериализуется в строку
заданного формата (например, JSON или XML) при помощи [[yii\web\ResponseFormatterInterface|форматтера ответа]].
Именно на этом стоит сосредоточится при разработке класса ресурса.
Вы можете указать какие данные включать в представление ресурса в виде массива путём переопределения методов
[[yii\base\Model::fields()|fields()]] и/или [[yii\base\Model::extraFields()|extraFields()]]. Разница между ними в том,
что первый определяет набор полей, которые всегда будут включены в массив, а второй определяет дополнительные поля, которые
пользователь может запросить через параметр `expand`:
```
// вернёт все поля объявленные в fields()
http://localhost/users
// вернёт только поля id и email, если они объявлены в методе fields()
http://localhost/users?fields=id,email
// вернёт все поля объявленные в fields() и поле profile если оно указано в extraFields()
http://localhost/users?expand=profile
// вернёт только id, email и profile, если они объявлены в fields() и extraFields()
http://localhost/users?fields=id,email&expand=profile
```
### Переопределение `fields()` <span id="overriding-fields"></span>
По умолчанию, [[yii\base\Model::fields()]] возвращает все атрибуты модели как поля, а
[[yii\db\ActiveRecord::fields()]] возвращает только те атрибуты, которые были объявлены в схеме БД.
Вы можете переопределить `fields()` для того, чтобы добавить, удалить, переименовать или переобъявить поля. Значение,
возвращаемое `fields()`, должно быть массивом. Его ключи — это названия полей. Значения могут быть либо именами
свойств/атрибутов, либо анонимными функциями, которые возвращают значение соответствующих свойств. Когда
название поля совпадает с именем аттрибута вы можете опустить ключ массива:
```php
// явное перечисление всех атрибутов лучше всего использовать когда вы хотите быть уверенным что изменение
// таблицы БД или атрибутов модели не повлияет на изменение полей, отдаваемых API (что важно для поддержки обратной
// совместимости API).
public function fields()
{
return [
// название поля совпадает с именем атрибута
'id',
// название поля "email", атрибут "email_address"
'email' => 'email_address',
// название поля "name", значение определяется callback-ом PHP
'name' => function () {
return $this->first_name . ' ' . $this->last_name;
},
];
}
// отбрасываем некоторые поля. Лучше всего использовать в случае наследования
public function fields()
{
$fields = parent::fields();
// удаляем небезопасные поля
unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']);
return $fields;
}
```
> Warning: По умолчанию все атрибуты модели будут включены в ответы API. Вы должны убедиться в том, что отдаются
> только безопасные данные. В противном случае для исключения небезопасных полей необходимо переопределить метод
> `fields()`. В приведённом выше примере мы исключаем `auth_key`, `password_hash` и `password_reset_token`.
### Переопределение `extraFields()` <span id="overriding-extra-fields"></span>
По умолчанию, [[yii\base\Model::extraFields()]] ничего не возвращает, а [[yii\db\ActiveRecord::extraFields()]]
возвращает названия заданных в БД связей.
Формат возвращаемых `extraFields()` данных такой же как у `fields()`. Как правило, `extraFields()`
используется для указания полей, значения которых являются объектами. Например учитывая следующее объявление полей
```php
public function fields()
{
return ['id', 'email'];
}
public function extraFields()
{
return ['profile'];
}
```
запрос `http://localhost/users?fields=id,email&expand=profile` может возвращать следующие JSON данные:
```php
[
{
"id": 100,
"email": "100@example.com",
"profile": {
"id": 100,
"age": 30,
}
},
...
]
```
## Ссылки <span id="links"></span>
Согласно [HATEOAS](http://en.wikipedia.org/wiki/HATEOAS), расшифровывающемуся как Hypermedia as the Engine of Application State,
RESTful API должны возвращать достаточно информации для того, чтобы клиенты могли определить возможные действия над ресурсами.
Ключевой момент HATEOAS заключается в том, чтобы возвращать вместе с данными набора гиперссылок, указывающих на связанную
с ресурсом информацию.
Поддержку HATEOAS в ваши классы ресурсов можно добавить реализовав интерфейс [[yii\web\Linkable]]. Этот интерфейс
содержит единственный метод [[yii\web\Linkable::getLinks()|getLinks()]], который возвращает список [[yii\web\Link|ссылок]].
Обычно вы должны вернуть хотя бы ссылку `self` с URL самого ресурса:
```php
use yii\db\ActiveRecord;
use yii\web\Link;
use yii\web\Linkable;
use yii\helpers\Url;
class User extends ActiveRecord implements Linkable
{
public function getLinks()
{
return [
Link::REL_SELF => Url::to(['user/view', 'id' => $this->id], true),
];
}
}
```
При отправке ответа объект `User` содержит поле `_links`, значение которого — ссылки, связанные с объектом:
```
{
"id": 100,
"email": "user@example.com",
// ...
"_links" => {
"self": {
"href": "https://example.com/users/100"
}
}
}
```
## Коллекции <span id="collections"></span>
Объекты ресурсов могут группироваться в *коллекции*. Каждая коллекция содержит список объектов ресурсов одного типа.
Несмотря на то, что коллекции можно представить в виде массива, удобнее использовать
[провайдеры данных](output-data-providers.md) так как они поддерживают сортировку и постраничную разбивку.
Для RESTful APIs, которые работают с коллекциями, данные возможности используются довольно часто. Например, следующее
действие контроллера возвращает провайдер данных для ресурса постов:
```php
namespace app\controllers;
use yii\rest\Controller;
use yii\data\ActiveDataProvider;
use app\models\Post;
class PostController extends Controller
{
public function actionIndex()
{
return new ActiveDataProvider([
'query' => Post::find(),
]);
}
}
```
При отправке ответа RESTful API, [[yii\rest\Serializer]] сериализует массив объектов ресурсов для текущей страницы.
Кроме того, он добавит HTTP заголовки, содержащие информацию о страницах:
* `X-Pagination-Total-Count`: общее количество ресурсов;
* `X-Pagination-Page-Count`: количество страниц;
* `X-Pagination-Current-Page`: текущая страница (начиная с 1);
* `X-Pagination-Per-Page`: количество ресурсов на страницу;
* `Link`: набор ссылок, позволяющий клиенту пройти все страницы ресурсов.
Примеры вы можете найти в разделе «[быстрый старт](rest-quick-start.md#trying-it-out)».

185
docs/guide-ru/rest-response-formatting.md

@ -1,185 +0,0 @@
Форматирование ответа
===================
При обработке RESTful API запросов приложение обычно выполняет следующие шаги, связанные с форматированием ответа:
1. Определяет различные факторы, которые могут повлиять на формат ответа, такие как media type, язык, версия и т.д.
Этот процесс также известен как [согласование содержимого](http://en.wikipedia.org/wiki/Content_negotiation).
2. Конвертирует объекты ресурсов в массивы, как описано в секции [Ресурсы](rest-resources.md).
Этим занимается [[yii\rest\Serializer]].
3. Конвертирует массивы в строки исходя из формата, определенного на этапе согласование содержимого. Это задача для
[[yii\web\ResponseFormatterInterface|форматтера ответов]], регистрируемого с помощью компонента приложения
[[yii\web\Response::formatters|response]].
## Согласование содержимого <span id="content-negotiation"></span>
Yii поддерживает согласование содержимого с помощью фильтра [[yii\filters\ContentNegotiator]]. Базовый класс
контроллера RESTful API - [[yii\rest\Controller]] - использует этот фильтр под именем `contentNegotiator`.
Фильтр обеспечивает соответствие формата ответа и определяет используемый язык. Например, если RESTful API запрос
содержит следующий заголовок:
```
Accept: application/json; q=1.0, */*; q=0.1
```
Он получит ответ в JSON-формате такого вида:
```
$ curl -i -H "Accept: application/json; q=1.0, */*; q=0.1" "http://localhost/users"
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
[
{
"id": 1,
...
},
{
"id": 2,
...
},
...
]
```
Под капотом происходит следующее: прежде, чем *действие* RESTful API контроллера будет выполнено, фильтр
[[yii\filters\ContentNegotiator]] проверит HTTP-заголовок `Accept` в запросе и установит, что
[[yii\web\Response::format|формат ответа]] должен быть в `'json'`. После того, как *действие* будет выполнено и вернет
итоговый объект ресурса или коллекцию, [[yii\rest\Serializer]] конвертирует результат в массив.
И, наконец, [[yii\web\JsonResponseFormatter]] сериализует массив в строку в формате JSON и включит ее в тело ответа.
По умолчанию, RESTful API поддерживает и JSON, и XML форматы. Для того, чтобы добавить поддержку нового формата,
вы должны установить свою конфигурацию для свойства [[yii\filters\ContentNegotiator::formats|formats]] у фильтра
`contentNegotiator`, например, с использованием поведения такого вида:
```php
use yii\web\Response;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_HTML;
return $behaviors;
}
```
Ключи свойства `formats` - это поддерживаемые MIME-типы, а их значения должны соответствовать именам
форматов ответа, которые установлены в [[yii\web\Response::formatters]].
## Сериализация данных <span id="data-serializing"></span>
Как уже описывалось выше, [[yii\rest\Serializer]] - это центральное место, отвечающее за конвертацию объектов ресурсов
или коллекций в массивы. Он реализует интерфейсы [[yii\base\Arrayable]] и [[yii\data\DataProviderInterface]].
Для объектов ресурсов как правило реализуется интерфейс [[yii\base\Arrayable]], а для коллекций -
[[yii\data\DataProviderInterface]].
Вы можете переконфигурировать сериализатор с помощью настройки свойства [[yii\rest\Controller::serializer]], используя
конфигурационный массив. Например, иногда вам может быть нужно помочь упростить разработку клиентской части
приложения с помощью добавления информации о пагинации непосредственно в тело ответа. Чтобы сделать это,
переконфигурируйте свойство [[yii\rest\Serializer::collectionEnvelope]] следующим образом:
```php
use yii\rest\ActiveController;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
public $serializer = [
'class' => 'yii\rest\Serializer',
'collectionEnvelope' => 'items',
];
}
```
Тогда вы можете получить следующий ответ на запрос `http://localhost/users`:
```
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"items": [
{
"id": 1,
...
},
{
"id": 2,
...
},
...
],
"_links": {
"self": {
"href": "http://localhost/users?page=1"
},
"next": {
"href": "http://localhost/users?page=2"
},
"last": {
"href": "http://localhost/users?page=50"
}
},
"_meta": {
"totalCount": 1000,
"pageCount": 50,
"currentPage": 1,
"perPage": 20
}
}
```
### Настройка форматирования JSON
Ответ в формате JSON генерируется при помощи класса [[yii\web\JsonResponseFormatter|JsonResponseFormatter]], который
использует внутри [[yii\helpers\Json|хелпер JSON]]. Данный форматтер гибко настраивается. Например,
опция [[yii\web\JsonResponseFormatter::$prettyPrint|$prettyPrint]] полезна на время разработки так как при
её использовании ответы получаются более читаемыми. [[yii\web\JsonResponseFormatter::$encodeOptions|$encodeOptions]]
может пригодиться для более тонкой настройки кодирования.
Свойство [[yii\web\Response::formatters|formatters]] компонента приложения `response` может быть
[сконфигурировано](concept-configuration.md) следующим образом:
```php
'response' => [
// ...
'formatters' => [
\yii\web\Response::FORMAT_JSON => [
'class' => 'yii\web\JsonResponseFormatter',
'prettyPrint' => YII_DEBUG, // используем "pretty" в режиме отладки
'encodeOptions' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE,
// ...
],
],
],
```
При работе с базой данных через [DAO](db-dao.md) все данные представляются в виде строк, что не всегда корректно.
Особенно учитывая, что в JSON для чисел есть соответствующий тип. При использовании ActiveRecord значения числовых
столбцов приводятся к integer на этапе выборки из базы: [[yii\db\ActiveRecord::populateRecord()]].

92
docs/guide-ru/rest-routing.md

@ -1,92 +0,0 @@
Маршрутизация
=============
Имея готовые классы ресурсов и контроллеров, можно получить доступ к ресурсам, используя URL вроде
`http://localhost/index.php?r=user/create`, подобно тому, как вы это делаете с обычными Web-приложениями.
На деле вам обычно хочется включить «красивые» URL-адреса и использовать все преимущества HTTP-методов (HTTP-verbs).
Например, чтобы запрос `POST /users` означал обращение к действию `user/create`.
Это может быть легко сделано с помощью настройки [компонента приложения](structure-application-components.md)
`urlManager` в конфигурации приложения следующим образом:
```php
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
],
]
```
Главная новинка в коде выше по сравнению с управлением URL-адресами в Web-приложениях состоит в использовании
[[yii\rest\UrlRule]] для маршрутизации запросов к RESTful API. Этот особый класс URL-правил будет
создавать целый набор дочерних URL-правил для поддержки маршрутизации и создания URL-адресов для указанного контроллера (или контроллеров).
Например, приведенный выше код является приближенным аналогом следующего набора правил:
```php
[
'PUT,PATCH users/<id>' => 'user/update',
'DELETE users/<id>' => 'user/delete',
'GET,HEAD users/<id>' => 'user/view',
'POST users' => 'user/create',
'GET,HEAD users' => 'user/index',
'users/<id>' => 'user/options',
'users' => 'user/options',
]
```
Этим правилом поддерживаются следующие точки входа в API:
* `GET /users`: разбитый на страницы список всех пользователей;
* `HEAD /users`: общая информация по списку пользователей;
* `POST /users`: создание нового пользователя;
* `GET /users/123`: подробная информация о пользователе 123;
* `HEAD /users/123`: общая информация о пользователе 123;
* `PATCH /users/123` и `PUT /users/123`: обновление пользователя 123;
* `DELETE /users/123`: удаление пользователя 123;
* `OPTIONS /users`: список HTTP-методов, поддерживаемые точкой входа `/users`;
* `OPTIONS /users/123`: список HTTP-методов, поддерживаемые точкой входа `/users/123`.
Вы можете настроить опции `only` и `except`, явно указав для них список действий, которые поддерживаются или
которые должны быть отключены, соответственно. Например:
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'except' => ['delete', 'create', 'update'],
],
```
Вы также можете настроить опции `patterns` или `extraPatterns` для переопределения существующих шаблонов или добавления новых шаблонов, поддерживаемых этим правилом.
Например, для включения нового действия `search` в точке входа `GET /users/search` настройте опцию `extraPatterns` следующим образом:
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'extraPatterns' => [
'GET search' => 'search',
],
]
```
Как вы могли заметить, ID контроллера `user` в этих точках входа используется в форме множественного числа (как `users`).
Это происходит потому, что [[yii\rest\UrlRule]] автоматически приводит идентификаторы контроллеров к множественной форме.
Вы можете отключить такое поведение, назначив свойству [[yii\rest\UrlRule::pluralize]] значение `false`.
> Info: Приведение ID контроллера к множественной форме производится в методе [[yii\helpers\Inflector::pluralize()]].
При этом соблюдаются правила английского языка. Например, `box` будет преобразован в `boxes`, а не в `boxs`.
В том случае, если автоматическое приведение к множественному числу вам не подходит, вы можете настроить
свойство [[yii\rest\UrlRule::controller]], где указать явное соответствие имени в URL и ID контроллера.
Например, код ниже ставит в соответствие имя `u` и ID контроллера `user`.
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => ['u' => 'user'],
]
```

112
docs/guide-ru/rest-versioning.md

@ -1,112 +0,0 @@
Версионирование
===============
Хороший API должен быть *версионирован*: изменения и новые возможности реализуются в новых версиях API, а не в одной и
той же версии. В отличие от Web-приложений, где у вас есть полный контроль и над серверным, и над клиентским кодом,
API используются клиентами, код которых вы не контролируете. Поэтому, обратная совместимость (BC) должна по возможности
сохраняться. Если ломающее её изменение необходимо, делать его нужно в новой версии API. Существующие клиенты могут
продолжать использовать старую, совместимую с ними версию API. Новые или обновлённые клиенты могут использовать новую
версию.
> Tip: Чтобы узнать больше о выборе версий обратитесь к [Semantic Versioning](http://semver.org/).
Общей практикой при реализации версионирования API является включение номера версии в URL-адрес вызова API-метода.
Например, `http://example.com/v1/users` означает вызов API `/users` версии 1. Другой способ версионирования API,
получивший недавно широкое распространение, состоит в добавлении номера версии в HTTP-заголовки запроса,
обычно в заголовок `Accept`:
```
// как параметр
Accept: application/json; version=v1
// как тип содержимого, определенный поставщиком API
Accept: application/vnd.company.myapp-v1+json
```
Оба способа имеют достоинства и недостатки, и вокруг них много споров. Ниже мы опишем реально работающую стратегию
версионирования API, которая является некоторой смесью этих двух способов:
* Помещать каждую мажорную версию реализации API в отдельный модуль, чей ID является номером мажорной версии (например, `v1`, `v2`).
Естественно, URL-адреса API будут содержать в себе номера мажорных версий.
* В пределах каждой мажорной версии (т.е. внутри соответствующего модуля) использовать HTTP-заголовок `Accept`
для определения номера минорной версии и писать условный код для соответствующих минорных версий.
В каждый модуль, обслуживающий мажорную версию, следует включать классы ресурсов и контроллеров,
обслуживающих эту конкретную версию. Для лучшего разделения ответственности кода вы можете составить общий набор
базовых классов ресурсов и контроллеров, и субклассировать их в каждом отдельно взятом модуле версии. Внутри дочерних классов
реализуйте конкретный код вроде метода `Model::fields()`.
Ваш код может быть организован примерно следующим образом:
```
api/
common/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
modules/
v1/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
Module.php
v2/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
Module.php
```
Конфигурация вашего приложения могла бы выглядеть так:
```php
return [
'modules' => [
'v1' => [
'class' => 'app\modules\v1\Module',
],
'v2' => [
'class' => 'app\modules\v2\Module',
],
],
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => ['v1/user', 'v1/post']],
['class' => 'yii\rest\UrlRule', 'controller' => ['v2/user', 'v2/post']],
],
],
],
];
```
В результате `http://example.com/v1/users` возвратит список пользователей API версии 1, в то время как
`http://example.com/v2/users` вернет список пользователей версии 2.
Благодаря использованию модулей код API различных мажорных версий может быть хорошо изолирован. И по-прежнему возможно
повторное использование кода между модулями через общие базовые классы и другие разделяемые классы.
Для работы с минорными номерами версий вы можете использовать преимущества согласования содержимого,
предоставляемого поведением [[yii\filters\ContentNegotiator|contentNegotiator]].
Определив тип поддерживаемого содержимого, поведение `contentNegotiator` установит значение
свойства [[yii\web\Response::acceptParams]].
Например, если запрос посылается с HTTP-заголовком `Accept: application/json; version=v1`, то после согласования содержимого
свойство [[yii\web\Response::acceptParams]] будет содержать значение `['version' => 'v1']`.
На основе информации о версии из `acceptParams` вы можете выбирать поведение в действиях, классах ресурсов,
сериализаторах и т.д.
Так как минорные версии требуют поддержания обратной совместимости, будем надеяться, что в вашем коде не так уж много
проверок на номер версии. В противном случае велики шансы, что вам нужна новая мажорная версия.

14
docs/guide-uk/README.md

@ -126,20 +126,6 @@ All Rights Reserved.
* **TBD** [HTTP кешування](caching-http.md)
Веб-сервіси RESTful
-------------------
* **TBD** [Швидкий старт](rest-quick-start.md)
* **TBD** [Ресурси](rest-resources.md)
* **TBD** [Контролери](rest-controllers.md)
* **TBD** [Маршрутизація](rest-routing.md)
* **TBD** [Форматування відповіді](rest-response-formatting.md)
* **TBD** [Аутентифікація](rest-authentication.md)
* [Обмеження частоти запитів](rest-rate-limiting.md)
* **TBD** [Версіонування](rest-versioning.md)
* **TBD** [Обробка помилок](rest-error-handling.md)
Інструменти розробника
----------------------

66
docs/guide-uk/rest-rate-limiting.md

@ -1,66 +0,0 @@
Обмеження частоти запитів
===============================
Для того, щоб уникнути зловживань, вам слід подумати про додавання обмеження частоти запитів до вашого API. Наприклад,
ви можете обмежити використання вашого API до 100 запитів протягом 10 хвилин для кожного користувача. Якщо від користувача
протягом цього періода часу надходить більша кількість запитів, буде повернута відповідь з кодом 429
("занадто багато запитів").
Для того, щоб увімкнути обмеження частоти запитів, *[[yii\web\User::identityClass|клас user identity]]* повинен реалізовувати
інтерфейс [[yii\filters\RateLimitInterface]]. Цей інтерфейс вимагає реалізації наступних трьох методів:
* `getRateLimit()`: повертає максимальну кількість дозволених запитів та період часу, наприклад `[100, 600]`, що
означає не більше 100 викликів API прогятом 600 секунд.
* `loadAllowance()`: повертає кількість дозволених запитів, що залишились, та мітку часу *UNIX* останньої перевірки обмеження.
* `saveAllowance()`: зберігає кількість дозволених запитів та поточну мітку часу *UNIX*.
Ви можете використовувати два стовпці в таблиці user для зберігання кількості дозволених запитів та час останньої перевірки.
У методах `loadAllowance()` та `saveAllowance()` можна реалізувати зчитування та зберігання значень цих стовбців відповідно
до даних поточного аутентифікованого користувача. Для покращення швидкодії можна спробувати зберігати цю
інформацію в кеш чи NoSQL-сховищі.
Реалізація у моделі `User` може виглядати наступним чином:
```php
public function getRateLimit($request, $action)
{
return [$this->rateLimit, 1]; // $rateLimit запитів на секунду
}
public function loadAllowance($request, $action)
{
return [$this->allowance, $this->allowance_updated_at];
}
public function saveAllowance($request, $action, $allowance, $timestamp)
{
$this->allowance = $allowance;
$this->allowance_updated_at = $timestamp;
$this->save();
}
```
Як тільки відповідний інтерфейс буде реалізований у класі identity, Yii почне автоматично перевіряти обмеження
частоти запитів за допомогою фільтра дій [[yii\filters\RateLimiter]] для [[yii\rest\Controller]]. При перевищенні
обмежень буде викинуто виключення [[yii\web\TooManyRequestsHttpException]].
Ви можете налаштувати обмеження частоти викликів у ваших класах REST-контролерів наступним чином:
```php
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['rateLimiter']['enableRateLimitHeaders'] = false;
return $behaviors;
}
```
При увімкненому обмеженні частоти запитів кожна відповідь, за замовчуванням, повертається з наступними HTTP-заголовками,
що містять таку інформацію про поточні обмеження:
* `X-Rate-Limit-Limit`: максимальна кількість запитів, дозволена протягом періоду часу
* `X-Rate-Limit-Remaining`: скільки залишилось дозволених запитів в поточний період часу
* `X-Rate-Limit-Reset`: скільки часу у секундах потрібно почекати до отримання максимальної кількості дозволених запитів
Ви можете відключити ці заголовки, встановивши властивість [[yii\filters\RateLimiter::enableRateLimitHeaders]] у `false`,
як показано у прикладі вище.

14
docs/guide/README.md

@ -130,20 +130,6 @@ Caching
* [HTTP Caching](caching-http.md)
RESTful Web Services
--------------------
* [Quick Start](rest-quick-start.md)
* [Resources](rest-resources.md)
* [Controllers](rest-controllers.md)
* [Routing](rest-routing.md)
* [Response Formatting](rest-response-formatting.md)
* [Authentication](rest-authentication.md)
* [Rate Limiting](rest-rate-limiting.md)
* [Versioning](rest-versioning.md)
* [Error Handling](rest-error-handling.md)
Development Tools
-----------------

127
docs/guide/rest-authentication.md

@ -1,127 +0,0 @@
Authentication
==============
Unlike Web applications, RESTful APIs are usually stateless, which means sessions or cookies should not
be used. Therefore, each request should come with some sort of authentication credentials because
the user authentication status may not be maintained by sessions or cookies. A common practice is
to send a secret access token with each request to authenticate the user. Since an access token
can be used to uniquely identify and authenticate a user, **API requests should always be sent
via HTTPS to prevent man-in-the-middle (MitM) attacks**.
There are different ways to send an access token:
* [HTTP Basic Auth](http://en.wikipedia.org/wiki/Basic_access_authentication): the access token
is sent as the username. This should only be used when an access token can be safely stored
on the API consumer side. For example, the API consumer is a program running on a server.
* Query parameter: the access token is sent as a query parameter in the API URL, e.g.,
`https://example.com/users?access-token=xxxxxxxx`. Because most Web servers will keep query
parameters in server logs, this approach should be mainly used to serve `JSONP` requests which
cannot use HTTP headers to send access tokens.
* [OAuth 2](http://oauth.net/2/): the access token is obtained by the consumer from an authorization
server and sent to the API server via [HTTP Bearer Tokens](http://tools.ietf.org/html/rfc6750),
according to the OAuth2 protocol.
Yii supports all of the above authentication methods. You can also easily create new authentication methods.
To enable authentication for your APIs, do the following steps:
1. Configure the `user` [application component](structure-application-components.md):
- Set the [[yii\web\User::enableSession|enableSession]] property to be `false`.
- Set the [[yii\web\User::loginUrl|loginUrl]] property to be `null` to show a HTTP 403 error instead of redirecting to the login page.
2. Specify which authentication methods you plan to use by configuring the `authenticator` behavior
in your REST controller classes.
3. Implement [[yii\web\IdentityInterface::findIdentityByAccessToken()]] in your [[yii\web\User::identityClass|user identity class]].
Step 1 is not required but is recommended for RESTful APIs which should be stateless. When [[yii\web\User::enableSession|enableSession]]
is `false`, the user authentication status will NOT be persisted across requests using sessions. Instead, authentication
will be performed for every request, which is accomplished by Step 2 and 3.
> Tip: You may configure [[yii\web\User::enableSession|enableSession]] of the `user` application component
> in application configurations if you are developing RESTful APIs in terms of an application. If you develop
> RESTful APIs as a module, you may put the following line in the module's `init()` method, like the following:
>
> ```php
> public function init()
> {
> parent::init();
> \Yii::$app->user->enableSession = false;
> }
> ```
For example, to use HTTP Basic Auth, you may configure the `authenticator` behavior as follows,
```php
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpBasicAuth::class,
];
return $behaviors;
}
```
If you want to support all three authentication methods explained above, you can use `CompositeAuth` like the following,
```php
use yii\filters\auth\CompositeAuth;
use yii\filters\auth\HttpBasicAuth;
use yii\filters\auth\HttpBearerAuth;
use yii\filters\auth\QueryParamAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => CompositeAuth::class,
'authMethods' => [
HttpBasicAuth::class,
HttpBearerAuth::class,
QueryParamAuth::class,
],
];
return $behaviors;
}
```
Each element in `authMethods` should be an auth method class name or a configuration array.
Implementation of `findIdentityByAccessToken()` is application specific. For example, in simple scenarios
when each user can only have one access token, you may store the access token in an `access_token` column
in the user table. The method can then be readily implemented in the `User` class as follows,
```php
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
class User extends ActiveRecord implements IdentityInterface
{
public static function findIdentityByAccessToken($token, $type = null)
{
return static::findOne(['access_token' => $token]);
}
}
```
After authentication is enabled as described above, for every API request, the requested controller
will try to authenticate the user in its `beforeAction()` step.
If authentication succeeds, the controller will perform other checks (such as rate limiting, authorization)
and then run the action. The authenticated user identity information can be retrieved via `Yii::$app->user->identity`.
If authentication fails, a response with HTTP status 401 will be sent back together with other appropriate headers
(such as a `WWW-Authenticate` header for HTTP Basic Auth).
## Authorization <span id="authorization"></span>
After a user is authenticated, you probably want to check if he or she has the permission to perform the requested
action for the requested resource. This process is called *authorization* which is covered in detail in
the [Authorization section](security-authorization.md).
If your controllers extend from [[yii\rest\ActiveController]], you may override
the [[yii\rest\ActiveController::checkAccess()|checkAccess()]] method to perform authorization check. The method
will be called by the built-in actions provided by [[yii\rest\ActiveController]].

191
docs/guide/rest-controllers.md

@ -1,191 +0,0 @@
Controllers
===========
After creating the resource classes and specifying how resource data should be formatted, the next thing
to do is to create controller actions to expose the resources to end users through RESTful APIs.
Yii provides two base controller classes to simplify your work of creating RESTful actions:
[[yii\rest\Controller]] and [[yii\rest\ActiveController]]. The difference between these two controllers
is that the latter provides a default set of actions that are specifically designed to deal with
resources represented as [Active Record](db-active-record.md). So if you are using [Active Record](db-active-record.md)
and are comfortable with the provided built-in actions, you may consider extending your controller classes
from [[yii\rest\ActiveController]], which will allow you to create powerful RESTful APIs with minimal code.
Both [[yii\rest\Controller]] and [[yii\rest\ActiveController]] provide the following features, some of which
will be described in detail in the next few sections:
* HTTP method validation;
* [Content negotiation and Data formatting](rest-response-formatting.md);
* [Authentication](rest-authentication.md);
* [Rate limiting](rest-rate-limiting.md).
[[yii\rest\ActiveController]] in addition provides the following features:
* A set of commonly needed actions: `index`, `view`, `create`, `update`, `delete`, `options`;
* User authorization in regard to the requested action and resource.
## Creating Controller Classes <span id="creating-controller"></span>
When creating a new controller class, a convention in naming the controller class is to use
the type name of the resource and use singular form. For example, to serve user information,
the controller may be named as `UserController`.
Creating a new action is similar to creating an action for a Web application. The only difference
is that instead of rendering the result using a view by calling the `render()` method, for RESTful actions
you directly return the data. The [[yii\rest\Controller::serializer|serializer]] and the
[[yii\web\Response|response object]] will handle the conversion from the original data to the requested
format. For example,
```php
public function actionView($id)
{
return User::findOne($id);
}
```
## Filters <span id="filters"></span>
Most RESTful API features provided by [[yii\rest\Controller]] are implemented in terms of [filters](structure-filters.md).
In particular, the following filters will be executed in the order they are listed:
* [[yii\filters\ContentNegotiator|contentNegotiator]]: supports content negotiation, to be explained in
the [Response Formatting](rest-response-formatting.md) section;
* [[yii\filters\VerbFilter|verbFilter]]: supports HTTP method validation;
* [[yii\filters\auth\AuthMethod|authenticator]]: supports user authentication, to be explained in
the [Authentication](rest-authentication.md) section;
* [[yii\filters\RateLimiter|rateLimiter]]: supports rate limiting, to be explained in
the [Rate Limiting](rest-rate-limiting.md) section.
These named filters are declared in the [[yii\rest\Controller::behaviors()|behaviors()]] method.
You may override this method to configure individual filters, disable some of them, or add your own filters.
For example, if you only want to use HTTP basic authentication, you may write the following code:
```php
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpBasicAuth::class,
];
return $behaviors;
}
```
### CORS <span id="cors"></span>
Adding the [Cross-Origin Resource Sharing](structure-filters.md#cors) filter to a controller is a bit more complicated
than adding other filters described above, because the CORS filter has to be applied before authentication methods
and thus needs a slightly different approach compared to other filters. Also authentication has to be disabled for the
[CORS Preflight requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests)
so that a browser can safely determine whether a request can be made beforehand without the need for sending
authentication credentials. The following shows the code that is needed to add the [[yii\filters\Cors]] filter
to an existing controller that extends from [[yii\rest\ActiveController]]:
```php
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
// remove authentication filter
$auth = $behaviors['authenticator'];
unset($behaviors['authenticator']);
// add CORS filter
$behaviors['corsFilter'] = [
'class' => \yii\filters\Cors::class,
];
// re-add authentication filter
$behaviors['authenticator'] = $auth;
// avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
$behaviors['authenticator']['except'] = ['options'];
return $behaviors;
}
```
## Extending `ActiveController` <span id="extending-active-controller"></span>
If your controller class extends from [[yii\rest\ActiveController]], you should set
its [[yii\rest\ActiveController::modelClass|modelClass]] property to be the name of the resource class
that you plan to serve through this controller. The class must extend from [[yii\db\ActiveRecord]].
### Customizing Actions <span id="customizing-actions"></span>
By default, [[yii\rest\ActiveController]] provides the following actions:
* [[yii\rest\IndexAction|index]]: list resources page by page;
* [[yii\rest\ViewAction|view]]: return the details of a specified resource;
* [[yii\rest\CreateAction|create]]: create a new resource;
* [[yii\rest\UpdateAction|update]]: update an existing resource;
* [[yii\rest\DeleteAction|delete]]: delete the specified resource;
* [[yii\rest\OptionsAction|options]]: return the supported HTTP methods.
All these actions are declared through the [[yii\rest\ActiveController::actions()|actions()]] method.
You may configure these actions or disable some of them by overriding the `actions()` method, like shown the following,
```php
public function actions()
{
$actions = parent::actions();
// disable the "delete" and "create" actions
unset($actions['delete'], $actions['create']);
// customize the data provider preparation with the "prepareDataProvider()" method
$actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider'];
return $actions;
}
public function prepareDataProvider()
{
// prepare and return a data provider for the "index" action
}
```
Please refer to the class references for individual action classes to learn what configuration options are available.
### Performing Access Check <span id="performing-access-check"></span>
When exposing resources through RESTful APIs, you often need to check if the current user has the permission
to access and manipulate the requested resource(s). With [[yii\rest\ActiveController]], this can be done
by overriding the [[yii\rest\ActiveController::checkAccess()|checkAccess()]] method like the following,
```php
/**
* Checks the privilege of the current user.
*
* This method should be overridden to check whether the current user has the privilege
* to run the specified action against the specified data model.
* If the user does not have access, a [[ForbiddenHttpException]] should be thrown.
*
* @param string $action the ID of the action to be executed
* @param \yii\base\Model $model the model to be accessed. If `null`, it means no specific model is being accessed.
* @param array $params additional parameters
* @throws ForbiddenHttpException if the user does not have access
*/
public function checkAccess($action, $model = null, $params = [])
{
// check if the user can access $action and $model
// throw ForbiddenHttpException if access should be denied
if ($action === 'update' || $action === 'delete') {
if ($model->author_id !== \Yii::$app->user->id)
throw new \yii\web\ForbiddenHttpException(sprintf('You can only %s articles that you\'ve created.', $action));
}
}
```
The `checkAccess()` method will be called by the default actions of [[yii\rest\ActiveController]]. If you create
new actions and also want to perform access check, you should call this method explicitly in the new actions.
> Tip: You may implement `checkAccess()` by using the [Role-Based Access Control (RBAC) component](security-authorization.md).

94
docs/guide/rest-error-handling.md

@ -1,94 +0,0 @@
Error Handling
==============
When handling a RESTful API request, if there is an error in the user request or if something unexpected
happens on the server, you may simply throw an exception to notify the user that something went wrong.
If you can identify the cause of the error (e.g., the requested resource does not exist), you should
consider throwing an exception along with a proper HTTP status code (e.g., [[yii\web\NotFoundHttpException]]
represents a 404 status code). Yii will send the response along with the corresponding HTTP status
code and text. Yii will also include the serialized representation of the
exception in the response body. For example:
```
HTTP/1.1 404 Not Found
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/7.1.0 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
```
The following list summarizes the HTTP status codes that are used by the Yii REST framework:
* `200`: OK. Everything worked as expected.
* `201`: A resource was successfully created in response to a `POST` request. The `Location` header
contains the URL pointing to the newly created resource.
* `204`: The request was handled successfully and the response contains no body content (like a `DELETE` request).
* `304`: The resource was not modified. You can use the cached version.
* `400`: Bad request. This could be caused by various actions by the user, such as providing invalid JSON
data in the request body, providing invalid action parameters, etc.
* `401`: Authentication failed.
* `403`: The authenticated user is not allowed to access the specified API endpoint.
* `404`: The requested resource does not exist.
* `405`: Method not allowed. Please check the `Allow` header for the allowed HTTP methods.
* `415`: Unsupported media type. The requested content type or version number is invalid.
* `422`: Data validation failed (in response to a `POST` request, for example). Please check the response body for detailed error messages.
* `429`: Too many requests. The request was rejected due to rate limiting.
* `500`: Internal server error. This could be caused by internal program errors.
## Customizing Error Response <span id="customizing-error-response"></span>
Sometimes you may want to customize the default error response format. For example, instead of relying on
using different HTTP statuses to indicate different errors, you would like to always use 200 as HTTP status
and enclose the actual HTTP status code as part of the JSON structure in the response, like shown in the following,
```
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/7.1.0 mod_ssl/2.2.26 OpenSSL/0.9.8y
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"success": false,
"data": {
"name": "Not Found Exception",
"message": "The requested resource was not found.",
"code": 0,
"status": 404
}
}
```
To achieve this goal, you can respond to the `beforeSend` event of the `response` component in the application configuration:
```php
return [
// ...
'components' => [
'response' => [
'class' => 'yii\web\Response',
'on beforeSend' => function ($event) {
$response = $event->sender;
if ($response->data !== null && Yii::$app->request->get('suppress_response_code')) {
$response->data = [
'success' => $response->isSuccessful,
'data' => $response->data,
];
$response->statusCode = 200;
}
},
],
],
];
```
The above code will reformat the response (for both successful and failed responses) as explained when
`suppress_response_code` is passed as a `GET` parameter.

209
docs/guide/rest-quick-start.md

@ -1,209 +0,0 @@
Quick Start
===========
Yii provides a whole set of tools to simplify the task of implementing RESTful Web Service APIs.
In particular, Yii supports the following features about RESTful APIs:
* Quick prototyping with support for common APIs for [Active Record](db-active-record.md);
* Response format negotiation (supporting JSON and XML by default);
* Customizable object serialization with support for selectable output fields;
* Proper formatting of collection data and validation errors;
* Collection pagination, filtering and sorting;
* Support for [HATEOAS](http://en.wikipedia.org/wiki/HATEOAS);
* Efficient routing with proper HTTP verb check;
* Built-in support for the `OPTIONS` and `HEAD` verbs;
* Authentication and authorization;
* Data caching and HTTP caching;
* Rate limiting;
In the following, we use an example to illustrate how you can build a set of RESTful APIs with some minimal coding effort.
Assume you want to expose the user data via RESTful APIs. The user data are stored in the `user` DB table,
and you have already created the [active record](db-active-record.md) class `app\models\User` to access the user data.
## Creating a Controller <span id="creating-controller"></span>
First, create a [controller](structure-controllers.md) class `app\controllers\UserController` as follows:
```php
namespace app\controllers;
use yii\rest\ActiveController;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
}
```
The controller class extends from [[yii\rest\ActiveController]], which implements a common set of RESTful actions.
By specifying [[yii\rest\ActiveController::modelClass|modelClass]]
as `app\models\User`, the controller knows which model can be used for fetching and manipulating data.
## Configuring URL Rules <span id="configuring-url-rules"></span>
Then, modify the configuration of the `urlManager` component in your application configuration:
```php
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
],
]
```
The above configuration mainly adds a URL rule for the `user` controller so that the user data
can be accessed and manipulated with pretty URLs and meaningful HTTP verbs.
> Note: Yii will automatically pluralize controller names for use in endpoints (see [Trying it Out](#trying-it-out) section below).
> You can configure this using the [[yii\rest\UrlRule::$pluralize]] property.
## Enabling JSON Input <span id="enabling-json-input"></span>
To let the API accept input data in JSON format, configure the [[yii\web\Request::$parsers|parsers]] property of
the `request` [application component](structure-application-components.md) to use the [[yii\web\JsonParser]] for JSON input:
```php
'request' => [
'parsers' => [
'application/json' => 'yii\web\JsonParser',
]
]
```
> Info: The above configuration is optional. Without the above configuration, the API would only recognize
`application/x-www-form-urlencoded` and `multipart/form-data` input formats.
## Trying it Out <span id="trying-it-out"></span>
With the above minimal amount of effort, you have already finished your task of creating the RESTful APIs
for accessing the user data. The APIs you have created include:
* `GET /users`: list all users page by page;
* `HEAD /users`: show the overview information of user listing;
* `POST /users`: create a new user;
* `GET /users/123`: return the details of the user 123;
* `HEAD /users/123`: show the overview information of user 123;
* `PATCH /users/123` and `PUT /users/123`: update the user 123;
* `DELETE /users/123`: delete the user 123;
* `OPTIONS /users`: show the supported verbs regarding endpoint `/users`;
* `OPTIONS /users/123`: show the supported verbs regarding endpoint `/users/123`.
You may access your APIs with the `curl` command like the following,
```
$ curl -i -H "Accept:application/json" "http://localhost/users"
HTTP/1.1 200 OK
...
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
[
{
"id": 1,
...
},
{
"id": 2,
...
},
...
]
```
Try changing the acceptable content type to be `application/xml`, and you will see the result
is returned in XML format:
```
$ curl -i -H "Accept:application/xml" "http://localhost/users"
HTTP/1.1 200 OK
...
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/xml
<?xml version="1.0" encoding="UTF-8"?>
<response>
<item>
<id>1</id>
...
</item>
<item>
<id>2</id>
...
</item>
...
</response>
```
The following command will create a new user by sending a POST request with the user data in JSON format:
```
$ curl -i -H "Accept:application/json" -H "Content-Type:application/json" -XPOST "http://localhost/users" -d '{"username": "example", "email": "user@example.com"}'
HTTP/1.1 201 Created
...
Location: http://localhost/users/1
Content-Length: 99
Content-Type: application/json; charset=UTF-8
{"id":1,"username":"example","email":"user@example.com","created_at":1414674789,"updated_at":1414674789}
```
> Tip: You may also access your APIs via Web browser by entering the URL `http://localhost/users`.
However, you may need some browser plugins to send specific request headers.
As you can see, in the response headers, there is information about the total count, page count, etc.
There are also links that allow you to navigate to other pages of data. For example, `http://localhost/users?page=2`
would give you the next page of the user data.
Using the `fields` and `expand` parameters, you may also specify which fields should be included in the result.
For example, the URL `http://localhost/users?fields=id,email` will only return the `id` and `email` fields.
> Info: You may have noticed that the result of `http://localhost/users` includes some sensitive fields,
> such as `password_hash`, `auth_key`. You certainly do not want these to appear in your API result.
> You can and should remove these fields from result as described in the [Resources](rest-resources.md) section.
Addionally, you can sort collections like `http://localhost/users?sort=email` or
`http://localhost/users?sort=-email`. Filtering collections like `http://localhost/users?filter[id]=10` or
`http://localhost/users?filter[email][like]=gmail.com` could be implemented using
data filters. See [Resources](rest-resources.md#filtering-collections) section for details.
## Summary <span id="summary"></span>
Using the Yii RESTful API framework, you implement an API endpoint in terms of a controller action, and you use
a controller to organize the actions that implement the endpoints for a single type of resource.
Resources are represented as data models which extend from the [[yii\base\Model]] class.
If you are working with databases (relational or NoSQL), it is recommended you use [[yii\db\ActiveRecord|ActiveRecord]]
to represent resources.
You may use [[yii\rest\UrlRule]] to simplify the routing to your API endpoints.
While not required, it is recommended that you develop your RESTful APIs as a separate application, different from
your Web front end and back end for easier maintenance.

66
docs/guide/rest-rate-limiting.md

@ -1,66 +0,0 @@
Rate Limiting
=============
To prevent abuse, you should consider adding *rate limiting* to your APIs. For example, you may want to limit the API usage
of each user to be at most 100 API calls within a period of 10 minutes. If too many requests are received from a user
within the stated period of the time, a response with status code 429 (meaning "Too Many Requests") should be returned.
To enable rate limiting, the [[yii\web\User::identityClass|user identity class]] should implement [[yii\filters\RateLimitInterface]].
This interface requires implementation of three methods:
* `getRateLimit()`: returns the maximum number of allowed requests and the time period (e.g., `[100, 600]` means there can be at most 100 API calls within 600 seconds).
* `loadAllowance()`: returns the number of remaining requests allowed and the corresponding UNIX timestamp
when the rate limit was last checked.
* `saveAllowance()`: saves both the number of remaining requests allowed and the current UNIX timestamp.
You may want to use two columns in the user table to record the allowance and timestamp information. With those defined,
then `loadAllowance()` and `saveAllowance()` can be implemented to read and save the values
of the two columns corresponding to the current authenticated user. To improve performance, you may also
consider storing these pieces of information in a cache or NoSQL storage.
Implementation in the `User` model could look like the following:
```php
public function getRateLimit($request, $action)
{
return [$this->rateLimit, 1]; // $rateLimit requests per second
}
public function loadAllowance($request, $action)
{
return [$this->allowance, $this->allowance_updated_at];
}
public function saveAllowance($request, $action, $allowance, $timestamp)
{
$this->allowance = $allowance;
$this->allowance_updated_at = $timestamp;
$this->save();
}
```
Once the identity class implements the required interface, Yii will automatically use [[yii\filters\RateLimiter]]
configured as an action filter for [[yii\rest\Controller]] to perform rate limiting check. The rate limiter
will throw a [[yii\web\TooManyRequestsHttpException]] when the rate limit is exceeded.
You may configure the rate limiter
as follows in your REST controller classes:
```php
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['rateLimiter']['enableRateLimitHeaders'] = false;
return $behaviors;
}
```
When rate limiting is enabled, by default every response will be sent with the following HTTP headers containing
the current rate limiting information:
* `X-Rate-Limit-Limit`, the maximum number of requests allowed with a time period
* `X-Rate-Limit-Remaining`, the number of remaining requests in the current time period
* `X-Rate-Limit-Reset`, the number of seconds to wait in order to get the maximum number of allowed requests
You may disable these headers by configuring [[yii\filters\RateLimiter::enableRateLimitHeaders]] to be `false`,
as shown in the above code example.

261
docs/guide/rest-resources.md

@ -1,261 +0,0 @@
Resources
=========
RESTful APIs are all about accessing and manipulating *resources*. You may view resources as
[models](structure-models.md) in the MVC paradigm.
While there is no restriction in how to represent a resource, in Yii you usually would represent resources
in terms of objects of [[yii\base\Model]] or its child classes (e.g. [[yii\db\ActiveRecord]]), for the
following reasons:
* [[yii\base\Model]] implements the [[yii\base\Arrayable]] interface, which allows you to
customize how you want to expose resource data through RESTful APIs.
* [[yii\base\Model]] supports [input validation](input-validation.md), which is useful if your RESTful APIs
need to support data input.
* [[yii\db\ActiveRecord]] provides powerful DB data access and manipulation support, which makes it
a perfect fit if your resource data is stored in databases.
In this section, we will mainly describe how a resource class extending from [[yii\base\Model]] (or its child classes)
can specify what data may be returned via RESTful APIs. If the resource class does not extend from [[yii\base\Model]],
then all its public member variables will be returned.
## Fields <span id="fields"></span>
When including a resource in a RESTful API response, the resource needs to be serialized into a string.
Yii breaks this process into two steps. First, the resource is converted into an array by [[yii\rest\Serializer]].
Second, the array is serialized into a string in a requested format (e.g. JSON, XML) by
[[yii\web\ResponseFormatterInterface|response formatters]]. The first step is what you should mainly focus when
developing a resource class.
By overriding [[yii\base\Model::fields()|fields()]] and/or [[yii\base\Model::extraFields()|extraFields()]],
you may specify what data, called *fields*, in the resource can be put into its array representation.
The difference between these two methods is that the former specifies the default set of fields which should
be included in the array representation, while the latter specifies additional fields which may be included
in the array if an end user requests for them via the `expand` query parameter. For example,
```
// returns all fields as declared in fields()
http://localhost/users
// only returns "id" and "email" fields, provided they are declared in fields()
http://localhost/users?fields=id,email
// returns all fields in fields() and field "profile" if it is in extraFields()
http://localhost/users?expand=profile
// returns all fields in fields(), "profile" if it is in extraFields() and "author" from profile if
// it is in extraFields() of profile model
http://localhost/comments?expand=post.author
// only returns "id" and "email" provided they are in fields() and "profile" if it is in extraFields()
http://localhost/users?fields=id,email&expand=profile
```
### Overriding `fields()` <span id="overriding-fields"></span>
By default, [[yii\base\Model::fields()]] returns all model attributes as fields, while
[[yii\db\ActiveRecord::fields()]] only returns the attributes which have been populated from DB.
You can override `fields()` to add, remove, rename or redefine fields. The return value of `fields()`
should be an array. The array keys are the field names, and the array values are the corresponding
field definitions which can be either property/attribute names or anonymous functions returning the
corresponding field values. In the special case when a field name is the same as its defining attribute
name, you can omit the array key. For example,
```php
// explicitly list every field, best used when you want to make sure the changes
// in your DB table or model attributes do not cause your field changes (to keep API backward compatibility).
public function fields()
{
return [
// field name is the same as the attribute name
'id',
// field name is "email", the corresponding attribute name is "email_address"
'email' => 'email_address',
// field name is "name", its value is defined by a PHP callback
'name' => function ($model) {
return $model->first_name . ' ' . $model->last_name;
},
];
}
// filter out some fields, best used when you want to inherit the parent implementation
// and blacklist some sensitive fields.
public function fields()
{
$fields = parent::fields();
// remove fields that contain sensitive information
unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']);
return $fields;
}
```
> Warning: Because by default all attributes of a model will be included in the API result, you should
> examine your data to make sure they do not contain sensitive information. If there is such information,
> you should override `fields()` to filter them out. In the above example, we choose
> to filter out `auth_key`, `password_hash` and `password_reset_token`.
### Overriding `extraFields()` <span id="overriding-extra-fields"></span>
By default, [[yii\base\Model::extraFields()]] returns an empty array, while [[yii\db\ActiveRecord::extraFields()]]
returns the names of the relations that have been populated from DB.
The return data format of `extraFields()` is the same as that of `fields()`. Usually, `extraFields()`
is mainly used to specify fields whose values are objects. For example, given the following field
declaration,
```php
public function fields()
{
return ['id', 'email'];
}
public function extraFields()
{
return ['profile'];
}
```
the request with `http://localhost/users?fields=id,email&expand=profile` may return the following JSON data:
```php
[
{
"id": 100,
"email": "100@example.com",
"profile": {
"id": 100,
"age": 30,
}
},
...
]
```
## Links <span id="links"></span>
[HATEOAS](http://en.wikipedia.org/wiki/HATEOAS), an abbreviation for Hypermedia as the Engine of Application State,
promotes that RESTful APIs should return information that allows clients to discover actions supported for the returned
resources. The key of HATEOAS is to return a set of hyperlinks with relation information when resource data are served
by the APIs.
Your resource classes may support HATEOAS by implementing the [[yii\web\Linkable]] interface. The interface
contains a single method [[yii\web\Linkable::getLinks()|getLinks()]] which should return a list of [[yii\web\Link|links]].
Typically, you should return at least the `self` link representing the URL to the resource object itself. For example,
```php
use yii\base\Model;
use yii\web\Link; // represents a link object as defined in JSON Hypermedia API Language.
use yii\web\Linkable;
use yii\helpers\Url;
class UserResource extends Model implements Linkable
{
public $id;
public $email;
//...
public function fields()
{
return ['id', 'email'];
}
public function extraFields()
{
return ['profile'];
}
public function getLinks()
{
return [
Link::REL_SELF => Url::to(['user/view', 'id' => $this->id], true),
'edit' => Url::to(['user/view', 'id' => $this->id], true),
'profile' => Url::to(['user/profile/view', 'id' => $this->id], true),
'index' => Url::to(['users'], true),
];
}
}
```
When a `UserResource` object is returned in a response, it will contain a `_links` element representing the links related
to the user, for example,
```
{
"id": 100,
"email": "user@example.com",
// ...
"_links" => {
"self": {
"href": "https://example.com/users/100"
},
"edit": {
"href": "https://example.com/users/100"
},
"profile": {
"href": "https://example.com/users/profile/100"
},
"index": {
"href": "https://example.com/users"
}
}
}
```
## Collections <span id="collections"></span>
Resource objects can be grouped into *collections*. Each collection contains a list of resource objects
of the same type.
While collections can be represented as arrays, it is usually more desirable to represent them
as [data providers](output-data-providers.md). This is because data providers support sorting and pagination
of resources, which is a commonly needed feature for RESTful APIs returning collections. For example,
the following action returns a data provider about the post resources:
```php
namespace app\controllers;
use yii\rest\Controller;
use yii\data\ActiveDataProvider;
use app\models\Post;
class PostController extends Controller
{
public function actionIndex()
{
return new ActiveDataProvider([
'query' => Post::find(),
]);
}
}
```
When a data provider is being sent in a RESTful API response, [[yii\rest\Serializer]] will take out the current
page of resources and serialize them as an array of resource objects. Additionally, [[yii\rest\Serializer]]
will also include the pagination information by the following HTTP headers:
* `X-Pagination-Total-Count`: The total number of resources;
* `X-Pagination-Page-Count`: The number of pages;
* `X-Pagination-Current-Page`: The current page (1-based);
* `X-Pagination-Per-Page`: The number of resources in each page;
* `Link`: A set of navigational links allowing client to traverse the resources page by page.
Since collection in REST APIs is a data provider, it shares all data provider features i.e. pagination and sorting.
An example may be found in the [Quick Start](rest-quick-start.md#trying-it-out) section.
### Filtering collections <span id="filtering-collections"></span>
Since version 2.0.13 Yii provides a facility to filter collections. An example can be found in the
[Quick Start](rest-quick-start.md#trying-it-out) guide. In case you're implementing an endpoint yourself,
filtering could be done as described in
[Filtering Data Providers using Data Filters](output-data-providers.md#filtering-data-providers-using-data-filters)
section of Data Providers guide.

187
docs/guide/rest-response-formatting.md

@ -1,187 +0,0 @@
Response Formatting
===================
When handling a RESTful API request, an application usually takes the following steps that are related
with response formatting:
1. Determine various factors that may affect the response format, such as media type, language, version, etc.
This process is also known as [content negotiation](http://en.wikipedia.org/wiki/Content_negotiation).
2. Convert resource objects into arrays, as described in the [Resources](rest-resources.md) section.
This is done by [[yii\rest\Serializer]].
3. Convert arrays into a string in the format as determined by the content negotiation step. This is
done by [[yii\web\ResponseFormatterInterface|response formatters]] registered with
the [[yii\web\Response::formatters|formatters]] property of the
`response` [application component](structure-application-components.md).
## Content Negotiation <span id="content-negotiation"></span>
Yii supports content negotiation via the [[yii\filters\ContentNegotiator]] filter. The RESTful API base
controller class [[yii\rest\Controller]] is equipped with this filter under the name of `contentNegotiator`.
The filter provides response format negotiation as well as language negotiation. For example, if a RESTful
API request contains the following header,
```
Accept: application/json; q=1.0, */*; q=0.1
```
it will get a response in JSON format, like the following:
```
$ curl -i -H "Accept: application/json; q=1.0, */*; q=0.1" "http://localhost/users"
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/7.1.0 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/5.4.20
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
[
{
"id": 1,
...
},
{
"id": 2,
...
},
...
]
```
Behind the scene, before a RESTful API controller action is executed, the [[yii\filters\ContentNegotiator]]
filter will check the `Accept` HTTP header in the request and set the [[yii\web\Response::format|response format]]
to be `'json'`. After the action is executed and returns the resulting resource object or collection,
[[yii\rest\Serializer]] will convert the result into an array. And finally, [[yii\web\JsonResponseFormatter]]
will serialize the array into a JSON string and include it in the response body.
By default, RESTful APIs support both JSON and XML formats. To support a new format, you should configure
the [[yii\filters\ContentNegotiator::formats|formats]] property of the `contentNegotiator` filter like
the following in your API controller classes:
```php
use yii\web\Response;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['contentNegotiator']['formats']['text/html'] = Response::FORMAT_HTML;
return $behaviors;
}
```
The keys of the `formats` property are the supported MIME types, while the values are the corresponding
response format names which must be supported in [[yii\web\Response::formatters]].
## Data Serializing <span id="data-serializing"></span>
As we have described above, [[yii\rest\Serializer]] is the central piece responsible for converting resource
objects or collections into arrays. It recognizes objects implementing [[yii\base\Arrayable]] as
well as [[yii\data\DataProviderInterface]]. The former is mainly implemented by resource objects, while
the latter resource collections.
You may configure the serializer by setting the [[yii\rest\Controller::serializer]] property with a configuration array.
For example, sometimes you may want to help simplify the client development work by including pagination information
directly in the response body. To do so, configure the [[yii\rest\Serializer::collectionEnvelope]] property
as follows:
```php
use yii\rest\ActiveController;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
public $serializer = [
'class' => 'yii\rest\Serializer',
'collectionEnvelope' => 'items',
];
}
```
You may then get the following response for request `http://localhost/users`:
```
HTTP/1.1 200 OK
Date: Sun, 02 Mar 2014 05:31:43 GMT
Server: Apache/2.2.26 (Unix) DAV/2 PHP/7.1.0 mod_ssl/2.2.26 OpenSSL/0.9.8y
X-Powered-By: PHP/7.1.0
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
{
"items": [
{
"id": 1,
...
},
{
"id": 2,
...
},
...
],
"_links": {
"self": {
"href": "http://localhost/users?page=1"
},
"next": {
"href": "http://localhost/users?page=2"
},
"last": {
"href": "http://localhost/users?page=50"
}
},
"_meta": {
"totalCount": 1000,
"pageCount": 50,
"currentPage": 1,
"perPage": 20
}
}
```
### 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](concept-configuration.md) like the following:
```php
'response' => [
// ...
'formatters' => [
\yii\web\Response::FORMAT_JSON => [
'class' => 'yii\web\JsonResponseFormatter',
'prettyPrint' => YII_DEBUG, // use "pretty" output in debug mode
'encodeOptions' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE,
// ...
],
],
],
```
When returning data from a database using the [DAO](db-dao.md) 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()]].

110
docs/guide/rest-routing.md

@ -1,110 +0,0 @@
Routing
=======
With resource and controller classes ready, you can access the resources using the URL like
`http://localhost/index.php?r=user/create`, similar to what you can do with normal Web applications.
In practice, you usually want to enable pretty URLs and take advantage of HTTP verbs.
For example, a request `POST /users` would mean accessing the `user/create` action.
This can be done easily by configuring the `urlManager` [application component](structure-application-components.md)
in the application configuration like the following:
```php
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
],
]
```
Compared to the URL management for Web applications, the main new thing above is the use of
[[yii\rest\UrlRule]] for routing RESTful API requests. This special URL rule class will
create a whole set of child URL rules to support routing and URL creation for the specified controller(s).
For example, the above code is roughly equivalent to the following rules:
```php
[
'PUT,PATCH users/<id>' => 'user/update',
'DELETE users/<id>' => 'user/delete',
'GET,HEAD users/<id>' => 'user/view',
'POST users' => 'user/create',
'GET,HEAD users' => 'user/index',
'users/<id>' => 'user/options',
'users' => 'user/options',
]
```
And the following API endpoints are supported by this rule:
* `GET /users`: list all users page by page;
* `HEAD /users`: show the overview information of user listing;
* `POST /users`: create a new user;
* `GET /users/123`: return the details of the user 123;
* `HEAD /users/123`: show the overview information of user 123;
* `PATCH /users/123` and `PUT /users/123`: update the user 123;
* `DELETE /users/123`: delete the user 123;
* `OPTIONS /users`: show the supported verbs regarding endpoint `/users`;
* `OPTIONS /users/123`: show the supported verbs regarding endpoint `/users/123`.
You may configure the `only` and `except` options to explicitly list which actions to support or which
actions should be disabled, respectively. For example,
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'except' => ['delete', 'create', 'update'],
],
```
You may also configure `patterns` or `extraPatterns` to redefine existing patterns or add new patterns supported by this rule.
For example, to support a new action `search` by the endpoint `GET /users/search`, configure the `extraPatterns` option as follows,
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'extraPatterns' => [
'GET search' => 'search',
],
]
```
You may have noticed that the controller ID `user` appears in plural form as `users` in the endpoint URLs.
This is because [[yii\rest\UrlRule]] automatically pluralizes controller IDs when creating child URL rules.
You may disable this behavior by setting [[yii\rest\UrlRule::pluralize]] to be `false`.
> Info: The pluralization of controller IDs is done by [[yii\helpers\Inflector::pluralize()]]. The method respects
special pluralization rules. For example, the word `box` will be pluralized as `boxes` instead of `boxs`.
In case when the automatic pluralization does not meet your requirement, you may also configure the
[[yii\rest\UrlRule::controller]] property to explicitly specify how to map a name used in endpoint URLs to
a controller ID. For example, the following code maps the name `u` to the controller ID `user`.
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => ['u' => 'user'],
]
```
## Extra configuration for contained rules
It could be useful to specify extra configuration that is applied to each rule contained within [[yii\rest\UrlRule]].
A good example would be specifying defaults for `expand` parameter:
```php
[
'class' => 'yii\rest\UrlRule',
'controller' => ['user'],
'ruleConfig' => [
'class' => 'yii\web\UrlRule',
'defaults' => [
'expand' => 'profile',
]
],
],
```

111
docs/guide/rest-versioning.md

@ -1,111 +0,0 @@
Versioning
==========
A good API is *versioned*: changes and new features are implemented in new versions of the API instead of continually altering just one version. Unlike Web applications, with which you have full control of both the client-side and server-side
code, APIs are meant to be used by clients beyond your control. For this reason, backward
compatibility (BC) of the APIs should be maintained whenever possible. If a change that may break BC is necessary, you should introduce it in new version of the API, and bump up the version number. Existing clients can continue to use the old, working version of the API; and new or upgraded clients can get the new functionality in the new API version.
> Tip: Refer to [Semantic Versioning](http://semver.org/)
for more information on designing API version numbers.
One common way to implement API versioning is to embed the version number in the API URLs.
For example, `http://example.com/v1/users` stands for the `/users` endpoint of API version 1.
Another method of API versioning,
which has gained momentum recently, is to put the version number in the HTTP request headers. This is typically done through the `Accept` header:
```
// via a parameter
Accept: application/json; version=v1
// via a vendor content type
Accept: application/vnd.company.myapp-v1+json
```
Both methods have their pros and cons, and there are a lot of debates about each approach. Below you'll see a practical strategy
for API versioning that is a mix of these two methods:
* Put each major version of API implementation in a separate module whose ID is the major version number (e.g. `v1`, `v2`).
Naturally, the API URLs will contain major version numbers.
* Within each major version (and thus within the corresponding module), use the `Accept` HTTP request header
to determine the minor version number and write conditional code to respond to the minor versions accordingly.
For each module serving a major version, the module should include the resource and controller classes
serving that specific version. To better separate code responsibility, you may keep a common set of
base resource and controller classes, and subclass them in each individual version module. Within the subclasses,
implement the concrete code such as `Model::fields()`.
Your code may be organized like the following:
```
api/
common/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
modules/
v1/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
Module.php
v2/
controllers/
UserController.php
PostController.php
models/
User.php
Post.php
Module.php
```
Your application configuration would look like:
```php
return [
'modules' => [
'v1' => [
'class' => 'app\modules\v1\Module',
],
'v2' => [
'class' => 'app\modules\v2\Module',
],
],
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => ['v1/user', 'v1/post']],
['class' => 'yii\rest\UrlRule', 'controller' => ['v2/user', 'v2/post']],
],
],
],
];
```
As a result of the above code, `http://example.com/v1/users` will return the list of users in version 1, while
`http://example.com/v2/users` will return version 2 users.
Thanks to modules, the code for different major versions can be well isolated. But modules make it still possible
to reuse code across the modules via common base classes and other shared resources.
To deal with minor version numbers, you may take advantage of the content negotiation
feature provided by the [[yii\filters\ContentNegotiator|contentNegotiator]] behavior. The `contentNegotiator`
behavior will set the [[yii\web\Response::acceptParams]] property when it determines which
content type to support.
For example, if a request is sent with the HTTP header `Accept: application/json; version=v1`,
after content negotiation, [[yii\web\Response::acceptParams]] will contain the value `['version' => 'v1']`.
Based on the version information in `acceptParams`, you may write conditional code in places
such as actions, resource classes, serializers, etc. to provide the appropriate functionality.
Since minor versions by definition require maintaining backward compatibility, hopefully there would not be many
version checks in your code. Otherwise, chances are that you may need to create a new major version.

10
docs/guide/structure-extensions.md

@ -399,6 +399,8 @@ registered on [Packagist](https://packagist.org/) and can be easily installed as
provides a set of commonly used auth clients, such as Facebook OAuth2 client, GitHub OAuth2 client.
- [yiisoft/yii2-bootstrap](https://github.com/yiisoft/yii2-bootstrap):
provides a set of widgets that encapsulate the [Bootstrap](http://getbootstrap.com/) components and plugins.
- [yiisoft/yii2-captcha](https://github.com/yiisoft/yii2-captcha):
provides an implementation for the CAPTCHA protection.
- [yiisoft/yii2-codeception](https://github.com/yiisoft/yii2-codeception):
provides testing support based on [Codeception](http://codeception.com/).
- [yiisoft/yii2-debug](https://github.com/yiisoft/yii2-debug):
@ -418,14 +420,22 @@ registered on [Packagist](https://packagist.org/) and can be easily installed as
provides an HTTP client.
- [yiisoft/yii2-imagine](https://github.com/yiisoft/yii2-imagine):
provides commonly used image manipulation functions based on [Imagine](http://imagine.readthedocs.org/).
- [yiisoft/yii2-jquery](https://github.com/yiisoft/yii2-jquery):
provides an integration of [JQuery](http://jquery.com/) and a set of widget behaviors for client side.
- [yiisoft/yii2-jui](https://github.com/yiisoft/yii2-jui):
provides a set of widgets that encapsulate the [JQuery UI](http://jqueryui.com/) interactions and widgets.
- [yiisoft/yii2-mongodb](https://github.com/yiisoft/yii2-mongodb):
provides the support for using [MongoDB](http://www.mongodb.org/). It includes features such as basic query,
Active Record, migrations, caching, code generation, etc.
- [yiisoft/yii2-mssql](https://github.com/yiisoft/yii2-mssql):
provides support for MSSQL Server database usage.
- [yiisoft/yii2-oracle](https://github.com/yiisoft/yii2-oracle):
provides support for Oracle database usage.
- [yiisoft/yii2-redis](https://github.com/yiisoft/yii2-redis):
provides the support for using [redis](http://redis.io/). It includes features such as basic query,
Active Record, caching, etc.
- [yiisoft/yii2-rest](https://github.com/yiisoft/yii2-rest):
provides the support for REST API server side creation.
- [yiisoft/yii2-smarty](https://github.com/yiisoft/yii2-smarty):
provides a template engine based on [Smarty](http://www.smarty.net/).
- [yiisoft/yii2-sphinx](https://github.com/yiisoft/yii2-sphinx):

Loading…
Cancel
Save