Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new interface application (implement RESTful-style web service services. API), implement RESTful web service, support internationalization (drivingly set the target language, default to simplified Chinese) (3)
1. RESTful web service, it is recommended to implement based on a separate interface application, at this time, it is implemented based on the API application
2. Create a new directory: \api\rests, this directory will be used as the operation method category directory of the RESTful web service
3. Create a new controller class \API\Controllers\UserController.php , and the controller class is extended from[[yii\rest\ActiveController]]. The realization of data serialization includes paging information in the response body to simplify the development of the client, as shown in Figure 1
<?php
/**
* Created by phpstorm.
* user: wangqiang
* Date: 2018/04/04
* TIME: 15:35
*/
Namespace API\Controllers;
use yii\rest\activecontroller;
Class UserController extends ActiveController
{
public $serializer =[
class=>API\RESTS\User\Serializer,
CollectionEnvelope=>items,
]#atfp_close_translate_span#;
/**
* @InheritDoc
*/
public function actions()
{
return[
index=> [
class=>API\RESTS\User\IndexAction,
ModelClass=> $this->modelClass,
CheckAccess=> [$this,CheckAccess]#ATFP_CLOSE_Translate_span#,
],
view=>[
class=>API\RESTS\User\ViewAction,
ModelClass=> $this->modelClass,
CheckAccess=> [$this,CheckAccess]#ATFP_CLOSE_Translate_span#,
],
Create=>[
class=>API\RESTS\User\CreateAction,
ModelClass=> $this->modelClass,
CheckAccess=> [$this,CheckAccess]#ATFP_CLOSE_Translate_span#,
scenerio=> $this->CreateScenario,
],
update=>[
class=>API\RESTS\User\UpdateAction,
ModelClass=> $this->modelClass,
CheckAccess=> [$this,CheckAccess]#ATFP_CLOSE_Translate_span#,
scenerio=> $this->UpdateScenario,
],
delete=>[
class=>API\RESTS\User\DeleteAction,
ModelClass=> $this->modelClass,
CheckAccess=> [$this,CheckAccess]#ATFP_CLOSE_Translate_span#,
],
options=>[
class=>API\RESTS\User\OptionsAction,
ModelClass=> $this->modelClass,
CheckAccess=> [$this,CheckAccess]#ATFP_CLOSE_Translate_span#,
],
];
}
}
Note: If only less behavior is supported, you can choose the following scheme, such as
public function actions()
{
$Actions = Parent::Actions();
$actions['view']['class']=API\RESTS\User\ViewAction;
return $actions;
}
4. When the content of the configuration is very complex, the common practice is to store it in one or more PHP files, which are called configuration files. A configuration file returns an array of php. Versioning of the versioned implementation, configuring the URL rules, modifying the configuration of the urlmanager component configured in the application, supporting the v1 module, supporting all behaviors, create a new:\api\config\urlmanager.php, as shown in Figure 2
<?php return[ class=> yii\web\urlmanager::class, enablePrettyURL=> true, EnableStrictParsing=> true, showscriptname=> false, rules=> [ [ class=>yii\rest\urlrule, controller=> [v1/user]#ATFP_CLOSE_Translate_span#, ], ], ];
5. Include \api\config\urlmanager.php in \api\config\main.php, edit \api\config\main.php
urlmanager=> require __dir__ ./urlmanager.php,
6. Implement the API of each major version in the main version number of a separate module ID, and generate the module based on the GII v1, open the URL: http://www.github-shuijingwan-yii2-app-advanced.localhost/gii/module , delete the directory: \api\modules\v1\views, as shown in Figure 3
7. Create a new \API\modules\v1\models\user.php, inherit to \api\models\user.php, as shown in Figure 4
Note: \api\modules\v1\models\user (only for v1 modules) > \api\models\user (for API applications only) > \common\logics\user.php (available for multiple applications such as API, frontend, etc.) > \common\models\user.php (limited to GII generation only) > \yii\db\ActiveRecord
<?php
/**
* Created by phpstorm.
* user: wangqiang
* Date: 2018/04/04
* TIME: 16:04
*/
Namespace API\modules\v1\models;
class user extends \api\models\user
{
}
8. \API\modules\v1\Controllers\DefaultController.php Renamed \API\modules\v1\Controllers\UserController.php, by specifying[[yii\rest\ActiveController::modelClass|modelClass]] As API\modules\v1\models\user, the controller can know which model to use to obtain and process data. Edit the code, as shown in Figure 5
Note: \api\modules\v1\Controllers\UserController.php (only for the v1 module) > \API\Controllers\UserController.php (only for API Application) > \yii\rest\ActiveController
<?php
Namespace API\modules\v1\controllers;
/**
* User controller for the `v1` module
*/
Class UserController extends \API\Controllers\UserController
{
public $modelClass =API\modules\v1\models\user;
}
9. To use the module in the application, you only need to add the module to the configuration of the application body.[[yii\base\Application::modules|modules]] in the list of attributes, the application body configuration of the following code Using the v1 module, edit \api\config\main.php, as shown in Figure 6
Modules=>[ v1=> [ class=> api\modules\v1\module::class, ]#ATFP_CLOSE_Translate_span#, ],
10. In Postman, get http://api.github-shuijingwan-yii2-app-advanced.localhost/v1 , 404 response, the format is HMTL, as shown in Figure 7
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="csrf-param" content="_csrf-api"> <meta name="csrf-token" content="00ssponpmjwowbzlftexhai8ksgetcknzkenlyrbzn YIAHZYZ6PC9XICYXPMWV7KZEPDQNYZG2UMKEZQXG38TW=="> <title>not found (#404)</title> <link href="/assets/73866dfd/css/bootstrap.css" rel="stylesheet"> <link href="/css/site.css" rel="stylesheet"> </head> <body> </body> </html>
11. For the solution of 404 response format is HTML, edit \api\config\main.php, and set the default response format to json
Response=>[ Format=> yii\web\response::format_json, ]#ATFP_CLOSE_Translate_span#,
12. In Postman, get http://api.github-shuijingwan-yii2-app-advanced.localhost/v1 , 404 response, the format is JSON, as shown in Figure 8
{
"name": "not found",
"message": "User not found.",
"code": 0,
"status": 404,
"type": "Yii\Web\\NotFoundHttpException"
}
13. RESTful APIs are usually stateless, so configure the User application component, edit \API\config\main.php
Note: Configure User Application Components:
install[[yii\web\User::enableSession|enableSession]] property is false.
install[[yii\web\User::loginUrl|loginUrl]] The attribute is null to display an HTTP 403 error instead of jumping to the login interface.
user=>[ IdentityClass=>API\Models\User, EnableSession=> false, loginurl=>null, EnableAutologin=> false, ]#ATFP_CLOSE_Translate_span#,
14. Copy the directory under \vendor\yiisoft\yii2\rest action.php, indexaction.php, optionsAction.php, viewaction.php, createaction.php, updateAction.php, deleteAction.php, serializer.php to directory \API\RESTS\User, if it is a directory with multiple words combined, it is recommended to use lowercase + underscore for the directory, refer to the URL: https://github. com/hfcorriez/fig-standards/blob/master/accepted/zh_cn/psr-0.md
15. Edit \API\RESTS\User\IndexAction.php, adjust namespace, inheritance relationship, query conditions, etc.
<?php
/**
* @Link http://www.yiiframework.com/
* @Copyright Copyright (C) 2008 Yii Software LLC
* @License http://www.yiiframework.com/license/
*/
Namespace API\RESTS\User;
use yii;
Use Yii\Data\ActiveDataProvider;
/**
* IndexAction implementations the API endpoint for listing multiple models.
;
* For more details and usage information on indexAction, see the[guide article on rest controllers](guide:rest-controllers).
;
* @author qiang wang <shuijingwanwq@163.com>
* @since 1.0
*/
Class IndexAction extends \yii\rest\indexaction
{
const status_deleted = 0; //status: deleted
const status_active = 10; // status: active
/**
* prepares the data provider that should return the requested collection of the models.
* @Return ActiveDataProvider
*/
protected function prepareDataProvider()
{
$requestParams = yii::$app->getRequest()->GetBodyParams();
if (empty($requestParams)) {
$requestParams = yii::$app->getRequest()->GetQueryParams();
}
$filter = null;
if ($this->datafilter !== null) {
$this->DataFilter = yii::CreateObject($this->DataFilter);
if ($this->datafilter->load($requestParams)) {
$filter = $this->datafilter->build();
if ($filter === False) {
return $this->datafilter;
}
}
}
if ($this->prepareDataProvider !== null) {
return call_user_func($this->preparadataProvider, $this, $filter);
}
/* @var $modelclass \yii\db\BaseActiveRecord */
$modelClass = $this->modelClass;
$query = $modelClass::find()->where(['status' => self::STATUS_ACTIVE]);
if (!empty($filter)) {
$query->andwhere($filter);
}
return yii::createObject([
class=> ActiveDataProvider::ClassName(),
query=> $query,
pagination=> [
params=> $requestParams,
]#ATFP_CLOSE_Translate_span#,
sort=>[
params=> $requestParams,
]#ATFP_CLOSE_Translate_span#,
]);
}
}
16. Edit \API\RESTS\User\Serializer.php, adjust the namespace, inheritance relationship, and response structure (response success: “code”: 10000,”message”,”data”; response failed: “code”: other numbers not equal to 10000, “message”) etc.
<?php
/**
* @Link http://www.yiiframework.com/
* @Copyright Copyright (C) 2008 Yii Software LLC
* @License http://www.yiiframework.com/license/
*/
Namespace API\RESTS\User;
use yii;
Use Yii\Data\DataProviderInterface;
/**
* Serializer converts resource objects and collections into array representation.
;
* Serializer is mainly used by REST CONTROLLERS to convert different objects into array representation
* So that they can be further turned into different formats, such as json, xml, by response formatters.
;
* The Default Implementation Handles Resources As[[Model]] objects and collections as objects
* implementation[[DataProviderInterface]]. You may override[[serialize()]] to handle more types.
;
* @author qiang wang <shuijingwanwq@163.com>
* @since 1.0
*/
class serializer extends \yii\rest\serializer
{
/**
* Serializes a data provider.
* @Param DataProviderInterface $DataProvider
* @Return Array the Array Representation of the Data Provider.
*/
protected function serialized dataProvider($dataProvider)
{
if ($this->preserveKeys) {
$models = $dataProvider->getModels();
} else {
$models = array_values($dataProvider->getModels());
}
$models = $this->serializeModels($models);
if (($pagination = $dataProvider->getPagination()) !== false) {
$this->AddPaginationHeaders($PAGINATION);
}
if ($this->request->getShead()) {
return null;
} elseif ($this->CollectionEnvelope === null) {
return $models;
}
$result =[
$this->CollectionEnvelope => $models,
]#atfp_close_translate_span#;
if (empty($result)['items'])) {
return['code' => 20001, 'message' => Yii::t('error', '20001')];
}
if ($pagination !== false) {
return['code' => 10000, 'message' => Yii::t('success', '10001'), 'data' => array_merge($result, $this->serializePagination($pagination))];
}
return['code' => 10000, 'message' => Yii::t('success', '10001'), 'data' => $result];
}
}
17. Edit \API\config\main.php to configure the I18n application component of the interface application
I18N=>[ translations=> [ model/*=> [ class=>yii\i18n\phpMessageSource, ForceTranslation=> true, basepath=>@common/messages, FileMap=>[ ]#ATFP_CLOSE_Translate_span#, ], ;=>[ class=>yii\i18n\phpMessageSource, ForceTranslation=> true, basepath=>@api/messages, FileMap=>[ ]#ATFP_CLOSE_Translate_span#, ], ], ],
18. Create a new language pack file: \api\messages\zh-cn\success.php (Simplified Chinese, the response is successful)
<?php return[ 10000 =>succeed, 10001 =>Get user list success, 10002 =>Successful user details, 10003 =>Create user success, 10004 =>Update user success, 10005 =>Delete user success, ]#atfp_close_translate_span#;
19. Create a new language pack file: \api\messages\zh-cn\error.php (Simplified Chinese, response failed)
<?php
return[
20000 =>Error,
20001 =>User list is empty,
20002 =>User ID: {id}, does not exist,
20003 =>User ID: {id}, the status is deleted,
20004 =>Data validation failed: {firsErrors},
]#atfp_close_translate_span#;
20. Create a new language pack file: \api\messages\en-us\success.php (English in the United States, the response is successful)
<?php return[ 10000 =>succeed, 10001 =>Get User List Success, 10002 =>Get User Details Success, 10003 =>Create user success, 10004 =>update user success, 10005 =>Delete user success, ]#atfp_close_translate_span#;
21. Create a new language pack file: \api\messages\en-us\error.php (English American, response failed)
<?php
return[
20000 =>Error,
20001 =>User List Is Empty,
20002 =>user id: {id}, does not exist,
20003 =>user id: {id}, the status is not active,
20004 =>data validation failed: {firsErrors},
]#atfp_close_translate_span#;
22. ContentNegotiator supports response content format processing and language processing. Determine the response content format and language by checking the GET parameter and the Accept HTTP header. Configure ContentNegotiator to support English American and Simplified Chinese. Edit \common\config\main.php
Note: If no language is detected in the request, use[[languages]] The first configuration item.
bootstrap=>['contentNegotiator'], components=>[ contentnegotiator=> [ class=>yii\filters\contentnegotiator, Languages=> [ en, en-us, ]#ATFP_CLOSE_Translate_span#, ], ],
Delete
sourceLanguage=>en-us, Language=>en,
23. In Postman, get http://api.github-shuijingwan-yii2-app-advanced.localhost/v1/users , 200 response, the message defaults to simplified Chinese, as shown in Figure 9
Note:
accept application/json; version=0.0
{
"code": 10000,
"message": "Get user list success",
"data": {
"items":[
{
"id": 1,
"username": "111111",
"Auth_key": "p66wcjvgql2toepyr-kc3z_rk7jjhmip",
"password_hash": "$2Y$13$qwv4xv1ylbtyn5cvx106vo6ktuoup/7kx3oac6cvpczhobkurc6ag",
"password_reset_token": null,
"email": "111111@163.com",
"status": 10,
"created_at": 1522821105,
"updated_at": 1522821105
},
{
"id": 2,
"username": "222222",
"auth_key": "mggfnpw6mytkzctyktoscyjay_xxu739",
"password_hash": "$2Y$13$XE0I4YJXL1Flvue8Q1YEU.NX8WH9HZZBOHSDBX2FL49ME15CQOSA2",
"password_reset_token": null,
"email": "222222@163.com",
"status": 10,
"created_at": 1522821319,
"updated_at": 1522821319
},
{
"id": 3,
"username": "333333",
"Auth_Key": "wpes81lh4eug0dp8fq7ely4mf1ucf-ph",
"password_hash": "$2Y$13$.2G63ZY8Q2wth/dwf.glve7c8kxkw3yct5gquvhnhpts2albro1ua",
"password_reset_token": null,
"email": "333333@163.com",
"status": 10,
"created_at": 1522823787,
"updated_at": 1522823787
},
{
"id": 4,
"username": "444444",
"Auth_Key": "SCN4SKHTFKG9YVRH1Q9JZHKKDDsr9H6A",
"password_hash": "$2Y$13$0RNX33MZIWC.FLSZMB0FUOCJAKMB1TLZZWCAUJACY/IXIM11MYQ0A",
"password_reset_token": null,
"email": "444444@163.com",
"status": 10,
"created_at": 1522823915,
"updated_at": 1522823915
}
]#ATFP_CLOSE_Translate_span#,
"_links": {
"self": {
"href": "http://api.github-shuijingwan-yii2-app-advanced.localhost/v1/users?user=1"
}
},
"_meta": {
"totalcount": 4,
"usercount": 1,
"currentuser": 1,
"peruser": 20
}
}
}
24. In Postman, get http://api.github-shuijingwan-yii2-app-advanced.localhost/v1/users , 200 response, the message is simplified Chinese, as shown in Figure 10
Note:
accept application/json; version=0.0
accept-language en
{
"code": 10000,
"message": "Get user list success",
"data": {
"items":[
{
"id": 1,
"username": "111111",
"Auth_key": "p66wcjvgql2toepyr-kc3z_rk7jjhmip",
"password_hash": "$2Y$13$qwv4xv1ylbtyn5cvx106vo6ktuoup/7kx3oac6cvpczhobkurc6ag",
"password_reset_token": null,
"email": "111111@163.com",
"status": 10,
"created_at": 1522821105,
"updated_at": 1522821105
},
{
"id": 2,
"username": "222222",
"auth_key": "mggfnpw6mytkzctyktoscyjay_xxu739",
"password_hash": "$2Y$13$XE0I4YJXL1Flvue8Q1YEU.NX8WH9HZZBOHSDBX2FL49ME15CQOSA2",
"password_reset_token": null,
"email": "222222@163.com",
"status": 10,
"created_at": 1522821319,
"updated_at": 1522821319
},
{
"id": 3,
"username": "333333",
"Auth_Key": "wpes81lh4eug0dp8fq7ely4mf1ucf-ph",
"password_hash": "$2Y$13$.2G63ZY8Q2wth/dwf.glve7c8kxkw3yct5gquvhnhpts2albro1ua",
"password_reset_token": null,
"email": "333333@163.com",
"status": 10,
"created_at": 1522823787,
"updated_at": 1522823787
},
{
"id": 4,
"username": "444444",
"Auth_Key": "SCN4SKHTFKG9YVRH1Q9JZHKKDDsr9H6A",
"password_hash": "$2Y$13$0RNX33MZIWC.FLSZMB0FUOCJAKMB1TLZZWCAUJACY/IXIM11MYQ0A",
"password_reset_token": null,
"email": "444444@163.com",
"status": 10,
"created_at": 1522823915,
"updated_at": 1522823915
}
]#ATFP_CLOSE_Translate_span#,
"_links": {
"self": {
"href": "http://api.github-shuijingwan-yii2-app-advanced.localhost/v1/users?user=1"
}
},
"_meta": {
"totalcount": 4,
"usercount": 1,
"currentuser": 1,
"peruser": 20
}
}
}
25, get /users/1: return the details of user 1, edit \api\rests\user\action.php, adjust the namespace, inheritance, response structure, etc.
<?php
/**
* @Link http://www.yiiframework.com/
* @Copyright Copyright (C) 2008 Yii Software LLC
* @License http://www.yiiframework.com/license/
*/
Namespace API\RESTS\User;
use yii;
use yii\db\ActiveCordInterface;
use yii\web\NotFoundHttpException;
/**
* Action is the base class for action classes that implement RESTful API.
;
* for more details and usage information on action, see the[guide article on rest controllers](guide:rest-controllers).
;
* @author qiang wang <shuijingwanwq@163.com>
* @since 1.0
*/
class action extends \yii\rest\action
{
/**
* return the data model based on the primary key given.
* If the data model is not found, A 404 HTTP Exception will be raised.
* @param string $id the id of the model to be loaded.
* The ID must be a string of the primary key values separated by commas.
* the order of the primary key values should follow that returned by the `primaryKey()` method
* of the model.
* @Return ActiveRecordInterface the Model Found
* @Throws NotFoundHttpException if the model cannot be found
*/
public function findModel($id)
{
if ($this->findModel !== null) {
return call_user_func($this->FindModel, $id, $this);
}
/* @var $modelclass ActiveRecordInterface */
$modelClass = $this->modelClass;
$keys = $modelClass::primaryKey();
if (count($keys) > 1) {
$values = explore(,, $id);
if (count($keys) === count($values)) {
$model = $modelClass::findone(array_combine($keys, $values));
}
} elseif ($id !== null) {
$model = $modelClass::findone($id);
}
if (isset($model)) {
return $model;
}
Throw New NotFoundHttpException(yii::t(Error, yii::t(Error, yii::t(Error,20002,['id' => $id])), 20002);
}
}
26. Edit \api\rests\user\viewaction.php, adjust namespace, inheritance relationship, response structure, etc.
<?php
/**
* @Link http://www.yiiframework.com/
* @Copyright Copyright (C) 2008 Yii Software LLC
* @License http://www.yiiframework.com/license/
*/
Namespace API\RESTS\User;
use yii;
/**
* ViewAction Implements the API endpoint for returning the detailed information about a model.
;
* for more details and usage information on viewing, see the[guide article on rest controllers](guide:rest-controllers).
;
* @author qiang wang <shuijingwanwq@163.com>
* @since 1.0
*/
Class ViewAction extends action
{
const status_deleted = 0; //status: deleted
const status_active = 10; // status: active
/**
* Displays a model.
* @param string $id the primary key of the model.
* @return \yii\db\ActiveCordInterface the model being displayed
*/
public function run($id)
{
$model = $this->findModel($id);
if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id, $model);
}
/* Judgment status, if deleted, return failure */
if ($model->status === self::status_deleted) {
return['code' => 20003, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '20003'), ['id' => $id]))];
}
return['code' => 10000, 'message' => Yii::t('success', '10002'), 'data' => $model];
}
}
27. In Postman, get http://api.github-shuijingwan-yii2-app-advanced.localhost/v1/users/1 , 200 responses, its status is active, as shown in Figure 11
Note:
accept application/json; version=0.0
accept-language en
{
"code": 10000,
"message": "Get user details successfully",
"data": {
"id": 1,
"username": "111111",
"Auth_key": "p66wcjvgql2toepyr-kc3z_rk7jjhmip",
"password_hash": "$2Y$13$qwv4xv1ylbtyn5cvx106vo6ktuoup/7kx3oac6cvpczhobkurc6ag",
"password_reset_token": null,
"email": "111111@163.com",
"status": 10,
"created_at": 1522821105,
"updated_at": 1522821105
}
}
28. In Postman, get http://api.github-shuijingwan-yii2-app-advanced.localhost/v1/users/5 , 404 response, the user does not exist, as shown in Figure 12
Note:
accept application/json; version=0.0
accept-language en-us
{
"name": "not found",
"message": "user id: 5, does not exist",
"code": 20002,
"status": 404,
"type": "Yii\Web\\NotFoundHttpException"
}
29, post /users: Create a new user, copy \api\models\signupform.php to \api\models\signup.php
<?php
namespace api\models;
use yii\base\model;
/**
* Signup
*/
class signup extends model
{
public $username;
public $email;
public $password;
/**
* {@inheritdoc}
*/
public function rules()
{
return[
[username,trim]#ATFP_CLOSE_Translate_span#,
['username', 'required'],
['username', 'unique', 'targetClass' => '\api\models\User'],
['username', 'string', 'min' => 2, 'max' => 255],
['email', 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'string', 'max' => 255],
['email', 'unique', 'targetClass' => '\api\models\User'],
['password', 'required'],
['password', 'string', 'min' => 6],
];
}
}
30. Create a new \API\modules\v1\models\signup.php, inherit to \api\models\signup.php
<?php
/**
* Created by phpstorm.
* user: wangqiang
* Date: 2018/04/08
* TIME: 10:48
*/
Namespace API\modules\v1\models;
class signup extends \api\models\signup
{
}
31, post /users: create a new user, edit \api\rests\user\createaction.php
<?php
/**
* @Link http://www.yiiframework.com/
* @Copyright Copyright (C) 2008 Yii Software LLC
* @License http://www.yiiframework.com/license/
*/
Namespace API\RESTS\User;
use yii;
use yii\base\model;
use API\models\signup;
use yii\helpers\url;
Use Yii\Web\ServerErrorHttpException;
/**
* CreateAction implementations the API endpoint for creating a new model from the given data.
;
* For more details and usage information on createAction, see the[guide article on rest controllers](guide:rest-controllers).
;
* @author qiang wang <shuijingwanwq@163.com>
* @since 1.0
*/
Class CreateAction extends action
{
/**
* @var string the scene to be assigned to the new model before it is validated and saved.
*/
public $scenario = model::scenario_default;
/**
* @var string the name of the view action. This property is need to create the URL when the model is successfully created.
*/
public $ViewAction =view;
/**
* Create a new model.
* @return \yii\db\ActiveCordInterface the model newly created
* @Throws ServerErrorHttpException if there is any error when creating the model
*/
public function run()
{
if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id);
}
$signup = new signup();
$signup->load(yii::$app->getRequest()->getBodyParams(),);
if (!$signup->validate()) {
if ($signup->hasErrors()) {
$response = yii::$app->getResponse();
$response->setStatusCode(422,data validation failed.);
foreach ($signup->GetfirsErrors() as $message) {
$firsErrors = $message;
break;
}
return['code' => 20004, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '20004'), ['firstErrors' => $firstErrors]))];
} elseif (!$signup->hasErrors()) {
Throw new ServerErrorHttpException(Failed to create the object for unknown reason.);
}
}
/* @var $model \yii\db\activerecord */
$model = new $this->modelClass([
scenerio=> $this->scenario,
]#atfp_close_translate_span#);
$model->username = $signup->username;
$model->email = $signup->email;
$model->setPassword($signup->password);
$model->GenerateAuthKey();
if ($model->save()) {
$response = yii::$app->getResponse();
$response->setStatusCode(201);
$id = implode(,, array_values($model->getPrimaryKey(true)));
$response->getHeaders()->set(location, url::torute([$this->viewAction, 'id' => $id], true));
} elseif ($model->hasErrors()) {
$response = yii::$app->getResponse();
$response->setStatusCode(422,data validation failed.);
foreach ($model->getfirsErrors() as $message) {
$firsErrors = $message;
break;
}
return['code' => 20004, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '20004'), ['firstErrors' => $firstErrors]))];
} elseif (!$model->hasErrors()) {
Throw new ServerErrorHttpException(Failed to create the object for unknown reason.);
}
return['code' => 10000, 'message' => Yii::t('success', '10003'), 'data' => $model];
}
}
32. In Postman, post http://api.github-shuijingwan-yii2-app-advanced.localhost/v1/users , 201 response, as shown in Figure 13
Note:
accept application/json; version=0.0
accept-language en
Accept-encoding gzip, deflate, br
content-type application/x-www-form-urlencoded
{
"code": 10000,
"message": "Create user success",
"data": {
"username": "555555",
"email": "555555@163.com",
"password_hash": "$2y$13$jcbrxulftlc4ffcrgwkpexrnfhup8xrgr/0orvpxc8ob3c3d2e/q",
"Auth_Key": "0eariaa02qw9j3s8ngwltglw34tpz98k",
"status": 10,
"created_at": 1523156052,
"updated_at": 1523156052,
"id": 5
}
}
33. In Postman, post http://api.github-shuijingwan-yii2-app-advanced.localhost/v1/users , the parameters remain as they are, 422 responds, as shown in Figure 14
Note:
accept application/json; version=0.0
accept-language en
Accept-encoding gzip, deflate, br
content-type application/x-www-form-urlencoded
{
"code": 20004,
"message": "Data validation failed: the value of username\"55555\" has been occupied."
}
34, put /users/5: update a user, create a new \api\models\userupdate.php
<?php
namespace api\models;
use yii\base\model;
/**
* UserUpdate
*/
Class UserUpdate extends model
{
public $id;
public $email;
public $password;
public $status;
const status_deleted = 0; //status: deleted
const status_active = 10; // status: active
/**
* {@inheritdoc}
*/
public function rules()
{
return[
[email,trim]#ATFP_CLOSE_Translate_span#,
['email', 'required'],
['email', 'email'],
['email', 'string', 'max' => 255],
['email', 'unique', 'targetClass' => '\api\models\User', 'filter' => ['!=', 'id', $this->id]],
['password', 'required'],
['password', 'string', 'min' => 6],
[['status'],in,range=>[self::STATUS_DELETED, self::STATUS_ACTIVE]],
];
}
}
35. Create a new \API\modules\v1\models\userupdate.php, inherit to \api\models\userupdate.php
<?php
/**
* Created by phpstorm.
* user: wangqiang
* Date: 2018/04/08
* TIME: 11:19
*/
Namespace API\modules\v1\models;
Class UserUpdate extends \API\Models\UserUpdate
{
}
36, put /users/4: update a user, edit \api\rests\user\updateaction.php
<?php
/**
* @Link http://www.yiiframework.com/
* @Copyright Copyright (C) 2008 Yii Software LLC
* @License http://www.yiiframework.com/license/
*/
Namespace API\RESTS\User;
use yii;
use yii\base\model;
use yii\db\activerecord;
Use API\Models\UserUpdate;
Use Yii\Web\ServerErrorHttpException;
/**
* UpdateAction implementations the API endpoint for updating a model.
;
* for more details and usage information on updateAction, see the[guide article on rest controllers](guide:rest-controllers).
;
* @author qiang wang <shuijingwanwq@163.com>
* @since 1.0
*/
Class UpdateAction extends action
{
/**
* @var String the scenario to be assigned to the model before it is validated and updated.
*/
public $scenario = model::scenario_default;
/**
* Updates an existing model.
* @param string $id the primary key of the model.
* @return \yii\db\ActiveRecordInterface the model being updated
* @Throws ServerErrorHttpException if there is any error when updating the model
*/
public function run($id)
{
/* @var $model ActiveRecord */
$model = $this->findModel($id);
if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id, $model);
}
$userUpdate = new UserUpdate();
$userupdate->id = $id;
$userUpdate->load(yii::$app->getRequest()->getBodyParams(),);
if (!$userUpdate->Validate()) {
if ($userupdate->hasErrors()) {
$response = yii::$app->getResponse();
$response->setStatusCode(422,data validation failed.);
foreach ($userUpdate->GetFirrors() as $message) {
$firsErrors = $message;
break;
}
return['code' => 20004, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '20004'), ['firstErrors' => $firstErrors]))];
} elseif (!$userUpdate->hasErrors()) {
Throw new ServerErrorHttpException(Failed to create the object for unknown reason.);
}
}
$model->scenario = $this->scenario;
$model->email = $userupdate->email;
$model->status = $userupdate->status;
$model->setPassword($userupdate->password);
$model->GenerateAuthKey();
if ($model->save() === False) {
if ($model->hasErrors()) {
$response = yii::$app->getResponse();
$response->setStatusCode(422,data validation failed.);
foreach ($model->getfirsErrors() as $message) {
$firsErrors = $message;
break;
}
return['code' => 20004, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '20004'), ['firstErrors' => $firstErrors]))];
} elseif (!$model->hasErrors()) {
Throw new ServerErrorHttpException(Failed to update the object for unknown reason.);
}
}
return['code' => 10000, 'message' => Yii::t('success', '10004'), 'data' => $model];
}
}
37. In Postman, put http://api.github-shuijingwan-yii2-app-advanced.localhost/v1/users/5 , 200 responses, as shown in Figure 15
{
"code": 10000,
"message": "Update user success",
"data": {
"id": 5,
"username": "555555",
"auth_key": "nxrym-o_ky4tadn758l47pqhlhssnjsz",
"password_hash": "$2Y$13$QB5Y3ZL7B8NYPDFMXC06YE8OAHYBCPP7P6WTOYHTLH2IDZHD06TS.",
"password_reset_token": null,
"email": "555555@qq.com",
"status": "0",
"created_at": 1523156052,
"updated_at": 1523165956
}
}
38. In Postman, put http://api.github-shuijingwan-yii2-app-advanced.localhost/v1/users/4 , 422 response, as shown in Figure 16
Note:
accept application/json; version=0.0
accept-language en-us
Accept-encoding gzip, deflate, br
content-type application/x-www-form-urlencoded
Body
The value of the email has been occupied by another user (if the value has not changed, it can be verified to pass)
{
"code": 20004,
"message": "data validation failed: email \"444444@163.com\" has already been taken."
}
39, delete /users/5: delete user 5, edit \api\rests\user\deleteaction.php
<?php
/**
* @Link http://www.yiiframework.com/
* @Copyright Copyright (C) 2008 Yii Software LLC
* @License http://www.yiiframework.com/license/
*/
Namespace API\RESTS\User;
use yii;
Use Yii\Web\ServerErrorHttpException;
/**
* DeleteAction implementations the API endpoint for deleting a model.
;
* for more details and usage information on deleteAction, see the[guide article on rest controllers](guide:rest-controllers).
;
* @author qiang wang <shuijingwanwq@163.com>
* @since 1.0
*/
class deleteAction extends action
{
/**
* deletes a model.
* @param mixed $id id of the model to be deleted.
* @Throws ServerErrorHttpException on Failure.
*/
public function run($id)
{
$model = $this->findModel($id);
if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id, $model);
}
if ($model->delete() === false) {
Throw new ServerErrorHttpException(Failed to delete the object for unknown reason.);
}
return['code' => 10000, 'message' => Yii::t('success', '10005')];
}
}
40. In Postman, delete http://api.github-shuijingwan-yii2-app-advanced.localhost/v1/users/5 , 200 responses, as shown in Figure 17
Note:
accept application/json; version=0.0
accept-language en
Accept-encoding gzip, deflate, br
{
"code": 10000,
"message": "Delete user success"
}
41. Edit \API\RESTS\User\OptionsAction.php
<?php
/**
* @Link http://www.yiiframework.com/
* @Copyright Copyright (C) 2008 Yii Software LLC
* @License http://www.yiiframework.com/license/
*/
Namespace API\RESTS\User;
use yii;
/**
* OptionsAction responses to the options request by sending back an `allow` header.
;
* for more details and usage information on options, see the[guide article on rest controllers](guide:rest-controllers).
;
* @author qiangxu <qiang.xue@gmail.com>
* @since 2.0
*/
Class OptionsAction extends \yii\rest\action
{
/**
* @var array the http verbs that are supported by the collection url
*/
public $CollectionOptions =['GET', 'POST', 'HEAD', 'OPTIONS'];
/**
* @var array the HTTP verbs that are supported by the resource URL
*/
public $resourceOptions =['GET', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'];
/**
* responses to the options request.
* @param string $id
*/
public function run($id = null)
{
if (yii::$app->GetRequest()->GetMethod() !==options) {
yii::$app->getResponse()->setStatusCode(405);
}
$options = $id === null ? $this->CollectionOptions : $this->resourceOptions;
$headers = yii::$app->getResponse()->GetHeaders();
$headers->set(allow, implode(,, $options));
$headers->set(access-control-allow-methods, implode(,, $options));
}
}
42. Options /Users: Displays verbs about the end/users supported, in Postman, options http://api.github-shuijingwan-yii2-app-advanced.localhost/v1/users , 200 responses, as shown in Figure 18
43. Options /Users/4: Display verbs about the end /users/4 support, in Postman, options http://api.github-shuijingwan-yii2-app-advanced.localhost/v1/users/1 , 200 responses, as shown in Figure 19
44. Due to[[yii\web\Response::format|response format]] The response format is not HTML, so it will not use error or exception views to display error messages, you can cancel the error action, edit \api\config\main.php
Delete
ErrorHandler=>[ ErrorAction=>site/error, ]#ATFP_CLOSE_Translate_span#,
45. Summary: The current supported behaviors: index, view, create, update, delete, and options, all of which are inherited, and then overwrite to achieve specific requirements.
![新建控制器类 \api\controllers\UserController.php ,控制器类扩展自 [[yii\rest\ActiveController]]。数据序列化的实现,在响应主体内包含分页信息来简化客户端的开发工作](http://www.shuijingwanwq.com/wp-content/uploads/2018/04/1-2.png)



![\api\modules\v1\controllers\DefaultController.php 重命名为 \api\modules\v1\controllers\UserController.php,通过指定 [[yii\rest\ActiveController::modelClass|modelClass]] 作为 api\modules\v1\models\User, 控制器就能知道使用哪个模型去获取和处理数据](http://www.shuijingwanwq.com/wp-content/uploads/2018/04/5-2.png)
![要在应用中使用模块,只需要将模块加入到应用主体配置的[[yii\base\Application::modules|modules]]属性的列表中, 如下代码的应用主体配置 使用 v1 模块,编辑 \api\config\main.php](http://www.shuijingwanwq.com/wp-content/uploads/2018/04/6-2.png)











