mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-02 04:37:42 +08:00
Add rest-versioning.md to translate into Russian [skip ci]
This commit is contained in:
107
docs/guide-ru/rest-versioning.md
Normal file
107
docs/guide-ru/rest-versioning.md
Normal file
@ -0,0 +1,107 @@
|
||||
Versioning
|
||||
==========
|
||||
|
||||
Your APIs should be versioned. Unlike Web applications which you have full control on both client side and server side
|
||||
code, for APIs you usually do not have control of the client code that consumes the APIs. Therefore, backward
|
||||
compatibility (BC) of the APIs should be maintained whenever possible, and if some BC-breaking changes must be
|
||||
introduced to the APIs, you should bump up the version number. You may refer to [Semantic Versioning](http://semver.org/)
|
||||
for more information about designing the version numbers of your APIs.
|
||||
|
||||
Regarding how to implement API versioning, a common practice is to embed the version number in the API URLs.
|
||||
For example, `http://example.com/v1/users` stands for `/users` API of version 1. Another method of API versioning
|
||||
which gains momentum recently is to put version numbers in the HTTP request headers, typically through the `Accept` header,
|
||||
like the following:
|
||||
|
||||
```
|
||||
// via a parameter
|
||||
Accept: application/json; version=v1
|
||||
// via a vendor content type
|
||||
Accept: application/vnd.company.myapp-v1+json
|
||||
```
|
||||
|
||||
Both methods have pros and cons, and there are a lot of debates about them. Below we describe a practical strategy
|
||||
of API versioning that is kind of 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, it should include the resource classes and the controller classes
|
||||
serving for 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
|
||||
v2/
|
||||
controllers/
|
||||
UserController.php
|
||||
PostController.php
|
||||
models/
|
||||
User.php
|
||||
Post.php
|
||||
```
|
||||
|
||||
Your application configuration would look like:
|
||||
|
||||
```php
|
||||
return [
|
||||
'modules' => [
|
||||
'v1' => [
|
||||
'basePath' => '@app/modules/v1',
|
||||
],
|
||||
'v2' => [
|
||||
'basePath' => '@app/modules/v2',
|
||||
],
|
||||
],
|
||||
'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, `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.
|
||||
|
||||
Using modules, code for different major versions can be well isolated. And it is still possible
|
||||
to reuse code across modules via common base classes and other shared classes.
|
||||
|
||||
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.
|
||||
|
||||
Since minor versions require maintaining backward compatibility, hopefully there are not much
|
||||
version checks in your code. Otherwise, chances are that you may need to create a new major version.
|
||||
Reference in New Issue
Block a user