Based on yiisoft/yii2-app-advanced, create a new repository yii2-app-advanced on github, and create a new remote procedure call application (implement hprose 2.0 for PHP RPC server), implement the corresponding RPC service of the page in the RPC directory, and implement the RPC client in the API directory
1. Implement the corresponding RPC service of the page in the RPC directory, create a remote procedure call HTTP server, and create a new \RPC\Controllers\ServerController.php
<?php
/**
* Created by PhpStorm.
* User: WangQiang
* Date: 2018/08/01
* Time: 18:02
*/
namespace rpc\controllers;
use Yii;
use yii\web\Controller;
use Hprose\Yii\Server;
/**
* 远程过程调用 HTTP 服务器
*
* @author Qiang Wang <shuijingwanwq@163.com>
* @since 1.0
*/
class ServerController extends Controller
{
public $enableCsrfValidation = false;
public function beforeAction($action)
{
parent::beforeAction($action);
$server = new Server();
$server->addMethod($action->actionMethod, $this, $action->controller->id . '_' . $action->id);
$server->start();
}
}
2. Create a new page model \rpc\models\page.php
<?php
namespace rpc\models;
class Page extends \common\logics\Page
{
}
3. Create a new page controller, \rpc\controllers\pagecontroller.php
<?php
/**
* Created by PhpStorm.
* User: WangQiang
* Date: 2018/08/01
* Time: 15:01
*/
namespace rpc\controllers;
use Yii;
use rpc\models\Page;
/**
* Page Controller
*
* @author Qiang Wang <shuijingwanwq@163.com>
* @since 1.0
*/
class PageController extends ServerController
{
/**
* 创建页面
*
* @param array $data 数据
*
* @param string $version 版本号(次版本号与修订号)
* 格式如下:
* 2.3
*
* @param string $language 区域和语言
* 格式如下:
* en-US
*
* @return mixed
*/
public function actionCreate(array $data, string $version = '', string $language = '')
{
return $data;
//echo 1;
//exit;
//$fileName = date('Y-m-d-H-i-s', time()) . '-' . microtime(true);
//file_put_contents('./../runtime/' . $fileName . '.txt', '0');
//return 1;
}
}
4. Then open the URL on the browser side:http://rpc.github-shuijingwan-yii2-app-advanced.localhost/page/create, see the following output: Fa2{u#s11″page_create”}z, as expected
5. Create a client through the factory method Create, edit \API\RESTS\page\CreateAction.php
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace api\rests\page;
use Yii;
use yii\base\Model;
use yii\helpers\Url;
use yii\web\ServerErrorHttpException;
use Hprose\Http\Client;
/**
* CreateAction implements 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 scenario 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';
/**
* Creates a new model.
* @return \yii\db\ActiveRecordInterface 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);
}
$client = Client::create('http://rpc.github-shuijingwan-yii2-app-advanced.localhost/page/create', false);
$page = $client->page_create([
'title' => 'title',
'body' => 'body',
]);
print_r($page);
exit;
/* @var $model \yii\db\ActiveRecord */
$model = new $this->modelClass([
'scenario' => $this->scenario,
]);
$model->load(Yii::$app->getRequest()->getBodyParams(), '');
if ($model->save()) {
$response = Yii::$app->getResponse();
$response->setStatusCode(201);
$id = implode(',', array_values($model->getPrimaryKey(true)));
$response->getHeaders()->set('Location', Url::toRoute([$this->viewAction, 'id' => $id], true));
} elseif ($model->hasErrors()) {
$response = Yii::$app->getResponse();
$response->setStatusCode(422, 'Data Validation Failed.');
foreach ($model->getFirstErrors() as $message) {
$firstErrors = $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', '10805'), 'data' => $model];
}
}
6. Postman in Postmanhttp://api.github-shuijingwan-yii2-app-advanced.localhost/v1/pages, the response failed
{
"name": "Exception",
"message": "28: Operation timed out after 30000 milliseconds with 0 bytes received",
"code": 0,
"type": "Exception",
"file": "E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\hprose\\hprose\\src\\Hprose\\Http\\Client.php",
"line": 276,
"stack-trace": [
"#0 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\hprose\\hprose\\src\\Hprose\\Http\\Client.php(295): Hprose\\Http\\Client->syncSendAndReceive('Cs11\"page_creat...', Object(stdClass))",
"#1 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\hprose\\hprose\\src\\Hprose\\Client.php(539): Hprose\\Http\\Client->sendAndReceive('Cs11\"page_creat...', Object(stdClass))",
"#2 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\hprose\\hprose\\src\\Hprose\\Client.php(109): Hprose\\Client->afterFilterHandler('Cs11\"page_creat...', Object(stdClass))",
"#3 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\hprose\\hprose\\src\\Hprose\\Client.php(504): Hprose\\Client->Hprose\\{closure}('Cs11\"page_creat...', Object(stdClass))",
"#4 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\hprose\\hprose\\src\\Hprose\\Client.php(518): Hprose\\Client->syncBeforeFilterHandler('Cs11\"page_creat...', Object(stdClass))",
"#5 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\hprose\\hprose\\src\\Hprose\\Client.php(106): Hprose\\Client->beforeFilterHandler('Cs11\"page_creat...', Object(stdClass))",
"#6 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\hprose\\hprose\\src\\Hprose\\Client.php(476): Hprose\\Client->Hprose\\{closure}('Cs11\"page_creat...', Object(stdClass))",
"#7 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\hprose\\hprose\\src\\Hprose\\Client.php(489): Hprose\\Client->syncInvokeHandler('page_create', Array, Object(stdClass))",
"#8 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\hprose\\hprose\\src\\Hprose\\Client.php(103): Hprose\\Client->invokeHandler('page_create', Array, Object(stdClass))",
"#9 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\hprose\\hprose\\src\\Hprose\\Client.php(608): Hprose\\Client->Hprose\\{closure}('page_create', Array, Object(stdClass))",
"#10 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\hprose\\hprose\\src\\Hprose\\Client.php(438): Hprose\\Client->invoke('page_create', Array)",
"#11 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\api\\rests\\page\\CreateAction.php(49): Hprose\\Client->__call('page_create', Array)",
"#12 [internal function]: api\\rests\\page\\CreateAction->run()",
"#13 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\yiisoft\\yii2\\base\\Action.php(94): call_user_func_array(Array, Array)",
"#14 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\yiisoft\\yii2\\base\\Controller.php(157): yii\\base\\Action->runWithParams(Array)",
"#15 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\yiisoft\\yii2\\base\\Module.php(528): yii\\base\\Controller->runAction('create', Array)",
"#16 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\yiisoft\\yii2\\web\\Application.php(103): yii\\base\\Module->runAction('v1/page/create', Array)",
"#17 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\vendor\\yiisoft\\yii2\\base\\Application.php(386): yii\\web\\Application->handleRequest(Object(yii\\web\\Request))",
"#18 E:\\wwwroot\\github-shuijingwan-yii2-app-advanced\\api\\web\\index.php(17): yii\\base\\Application->run()",
"#19 {main}"
]
}
7. The above reasons are because the Nginx PHP environment under Windows does not support concurrency. When multiple domain names are accessed at the same time and pointed to your local service at the same time, concurrency is not supported. In nginx.conf Modify the port number of fastcgi_pass for different servers, and start multiple php-cgi. as shown in Figure 1
## FRONTEND ##
server {
charset utf-8;
client_max_body_size 128M;
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name www.github-shuijingwan-yii2-app-advanced.localhost;
root E:/wwwroot/github-shuijingwan-yii2-app-advanced/frontend/web;
index index.php;
access_log logs/www.github-shuijingwan-yii2-app-advanced.localhost.access.log;
error_log logs/www.github-shuijingwan-yii2-app-advanced.localhost.error.log;
location / {
# Redirect everything that isn't a real file to index.php
try_files $uri $uri/ /index.php$is_args$args;
}
# uncomment to avoid processing of calls to non-existing static files by Yii
#location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
# try_files $uri =404;
#}
#error_page 404 /404.html;
# deny accessing php files for the /assets directory
location ~ ^/assets/.*\.php$ {
deny all;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
#fastcgi_pass unix:/var/run/php5-fpm.sock;
try_files $uri =404;
}
location ~* /\. {
deny all;
}
}
## BACKEND ##
server {
charset utf-8;
client_max_body_size 128M;
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name backend.github-shuijingwan-yii2-app-advanced.localhost;
root E:/wwwroot/github-shuijingwan-yii2-app-advanced/backend/web;
index index.php;
access_log logs/backend.github-shuijingwan-yii2-app-advanced.localhost.access.log;
error_log logs/backend.github-shuijingwan-yii2-app-advanced.localhost.error.log;
location / {
# Redirect everything that isn't a real file to index.php
try_files $uri $uri/ /index.php$is_args$args;
}
# uncomment to avoid processing of calls to non-existing static files by Yii
#location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
# try_files $uri =404;
#}
#error_page 404 /404.html;
# deny accessing php files for the /assets directory
location ~ ^/assets/.*\.php$ {
deny all;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
#fastcgi_pass unix:/var/run/php5-fpm.sock;
try_files $uri =404;
}
location ~* /\. {
deny all;
}
}
## API ##
server {
charset utf-8;
client_max_body_size 128M;
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name api.github-shuijingwan-yii2-app-advanced.localhost;
root E:/wwwroot/github-shuijingwan-yii2-app-advanced/api/web;
index index.php;
access_log logs/api.github-shuijingwan-yii2-app-advanced.localhost.access.log;
error_log logs/api.github-shuijingwan-yii2-app-advanced.localhost.error.log;
location / {
# Redirect everything that isn't a real file to index.php
try_files $uri $uri/ /index.php$is_args$args;
}
# uncomment to avoid processing of calls to non-existing static files by Yii
#location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
# try_files $uri =404;
#}
#error_page 404 /404.html;
# deny accessing php files for the /assets directory
location ~ ^/assets/.*\.php$ {
deny all;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9001;
#fastcgi_pass unix:/var/run/php5-fpm.sock;
try_files $uri =404;
}
location ~* /\. {
deny all;
}
}
## RPC ##
server {
charset utf-8;
client_max_body_size 128M;
listen 80; ## listen for ipv4
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
server_name rpc.github-shuijingwan-yii2-app-advanced.localhost;
root E:/wwwroot/github-shuijingwan-yii2-app-advanced/rpc/web;
index index.php;
access_log logs/rpc.github-shuijingwan-yii2-app-advanced.localhost.access.log;
error_log logs/rpc.github-shuijingwan-yii2-app-advanced.localhost.error.log;
location / {
# Redirect everything that isn't a real file to index.php
try_files $uri $uri/ /index.php$is_args$args;
}
# uncomment to avoid processing of calls to non-existing static files by Yii
#location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
# try_files $uri =404;
#}
#error_page 404 /404.html;
# deny accessing php files for the /assets directory
location ~ ^/assets/.*\.php$ {
deny all;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
#fastcgi_pass unix:/var/run/php5-fpm.sock;
try_files $uri =404;
}
location ~* /\. {
deny all;
}
}
## MISC ##
### WWW Redirect ###
server {
listen 80;
server_name github-shuijingwan-yii2-app-advanced.localhost;
return 301 http://www.github-shuijingwan-yii2-app-advanced.localhost$request_uri;
}
8. Postman in Postmanhttp://api.github-shuijingwan-yii2-app-a-client.localhost/v1/pages, respond to success
Array
(
[title] => title
[body] => body
)
9. Create a new module V1, realize version control based on the module, open:http://www.github-shuijingwan-yii2-app-advanced.localhost/gii/module, generate module V1, as shown in Figure 2
10. Rename \rpc\modules\v1\controllers\defaultcontroller.php to \rpc\modules\v1\controllers\pagecontroller.php
<?php
namespace rpc\modules\v1\controllers;
/**
* Page controller for the `v1` module
*/
class PageController extends \rpc\controllers\PageController
{
public $modelClass = 'rpc\modules\v1\models\Page';
}
11. Delete \rpc\modules\v1\views
12. Copy \api\models\page.php, \api\models\pagequery.php, \api\models\pagesearch.php is \rpc\models\page.php, \rpc\models\pagequery.php, \rpc\models\pagesearch.php, adjust the namespace
13. Copy \API\modules\v1\models\page.php, \api\modules\v1\model s\pagequery.php, \api\modules\v1\models\pagesearch.php for \rpc\modules\v1\models\page.php, \rpc\modules\v1\models\p AgeQuery.php, \rpc\modules\v1\models\pagesearch.php, adjust the namespace
14. Edit \rpc\config\main.php to add the module to the list of modules properties configured by the application body
'modules' => [
'v1' => [
'class' => rpc\modules\v1\Module::class,
],
],
15. Open the URL on the browser side:http://rpc.github-shuijingwan-yii2-app-advanced.localhost/v1/page/create, see the following output: Fa2{u#s11″page_create”}z, as expected
16. Create a client through the factory method create, edit \api\rests\page\createaction.php, and adjust the http service address
$client = Client::create('http://rpc.github-shuijingwan-yii2-app-advanced.localhost/v1/page/create', false);
$page = $client->page_create([
'title' => 'title',
'body' => 'body',
]);
print_r($page);
exit;
17. Postman in Postmanhttp://api.github-shuijingwan-yii2-app-advanced.localhost/v1/pages, the response is normal
Array
(
[title] => title
[body] => body
)
18. Edit \environments\dev\common\config\params-local.php, \environments\prod\common\config\params-local.php
<?php
return [
// RPC HTTP 服务地址
'rpc' => [
'hostInfo' => 'http://rpc.github-shuijingwan-yii2-app-advanced.localhost', // HOME URL
'baseUrl' => '/v1', // BASE URL
],
];
19. Create the basic class of the new RPC client, \common\logics\rpc\model.php
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/08/02
* Time: 13:12
*/
namespace common\logics\rpc;
use Yii;
use Hprose\Http\Client;
/**
* RPC 客户端的基础类
*
* @author Qiang Wang <shuijingwanwq@163.com>
* @since 1.0
*/
class Model extends \yii\base\Model
{
/**
* 创建一个同步的 HTTP 客户端
*
* @param string $controllerId 控制器ID
* 格式如下:
* page
*
* @param string $actionId 方法ID
* 格式如下:
* create
*
* @return object $client 同步的 HTTP 客户端
*/
public static function client($controllerId, $actionId)
{
$url = Yii::$app->params['rpc']['hostInfo'] . Yii::$app->params['rpc']['baseUrl'];
$client = Client::create($url . '/' . $controllerId . '/' . $actionId, false);
return $client->$controllerId;
}
}
20. Create the public logic class of the new page model, \common\logics\rpc\page.php, define the model attributes, scene (block assignment), and validation rules (preliminary verification of the request data to avoid obvious inconsistency of the rules data, penetrate to the RPC server)
<?php
namespace common\logics\rpc;
use Yii;
/**
* 页面模型
*/
class Page extends Model
{
const STATUS_DELETED = -1; //状态:删除
const STATUS_DISABLED = 0; //状态:禁用
const STATUS_DRAFT = 1; //状态:草稿
const STATUS_PUBLISHED = 2; //状态:发布
const CONTROLLER_ID = 'page'; //控制器ID
const SCENARIO_CREATE = 'create';
public $slug;
public $title;
public $body;
public $view;
public $status;
/**
* {@inheritdoc}
*/
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_CREATE] = ['slug', 'title', 'body', 'view', 'status'];
return $scenarios;
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['title', 'body'], 'required'],
[['body'], 'string'],
[['view', 'status'], 'integer'],
[['slug', 'title'], 'string', 'max' => 255],
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'slug' => Yii::t('model/rpc/page', 'Slug'),
'title' => Yii::t('model/rpc/page', 'Title'),
'body' => Yii::t('model/rpc/page', 'Body'),
'view' => Yii::t('model/rpc/page', 'View'),
'status' => Yii::t('model/rpc/page', 'Status'),
];
}
/**
* 创建页面
*
* @param array $data 数据
*
* @param string $version 版本号(次版本号与修订号)
* 格式如下:
* 2.3
*
* @param string $language 区域和语言
* 格式如下:
* en-US
*
* @return array
*/
public function create(array $data, string $version, string $language)
{
$actionId = 'create';
return self::client(self::CONTROLLER_ID, $actionId)->$actionId($data, $version, $language);
}
}
21. Create new \API\Models\rpc\page.php
<?php
namespace api\models\rpc;
class Page extends \common\logics\rpc\Page
{
}
22. Create new \API\modules\v1\models\rpc\page.php
<?php
/**
* Created by PhpStorm.
* User: WangQiang
* Date: 2018/08/02
* Time: 13:04
*/
namespace api\modules\v1\models\rpc;
class Page extends \api\models\rpc\Page
{
}
23. Edit \api\modules\v1\controllers\pagecontroller.php, specify the model class
<?php
namespace api\modules\v1\controllers;
/**
* Page controller for the `v1` module
*/
class PageController extends \api\controllers\PageController
{
public $modelClass = 'api\modules\v1\models\rpc\Page';
}
23. Edit \common\logics\page.php to define the scenario
<?php
namespace common\logics;
use Yii;
use yii\behaviors\SluggableBehavior;
use yii\behaviors\TimestampBehavior;
use yii2tech\ar\softdelete\SoftDeleteBehavior;
use yii\helpers\ArrayHelper;
class Page extends \common\models\Page
{
const STATUS_DELETED = -1; //状态:删除
const STATUS_DISABLED = 0; //状态:禁用
const STATUS_DRAFT = 1; //状态:草稿
const STATUS_PUBLISHED = 2; //状态:发布
const SCENARIO_CREATE = 'create';
/**
* @inheritdoc
*/
public function behaviors()
{
return [
'timestampBehavior' => [
'class' => TimestampBehavior::className(),
'attributes' => [
self::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
self::EVENT_BEFORE_UPDATE => 'updated_at',
SoftDeleteBehavior::EVENT_BEFORE_SOFT_DELETE => 'updated_at',
]
],
'slug' => [
'class' => SluggableBehavior::className(),
'attribute' => 'title',
'ensureUnique' => true,
'immutable' => true
],
'softDeleteBehavior' => [
'class' => SoftDeleteBehavior::className(),
'softDeleteAttributeValues' => [
'status' => self::STATUS_DELETED
],
],
];
}
/**
* {@inheritdoc}
*/
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_CREATE] = ['slug', 'title', 'body', 'view', 'status'];
return $scenarios;
}
/**
* @inheritdoc
*/
public function rules()
{
$rules = [
[['title', 'body'], 'required'],
[['slug'], 'unique'],
['view', 'default', 'value' => 0],
['status', 'default', 'value' => self::STATUS_DRAFT],
];
$parentRules = parent::rules();
unset($parentRules[0]);
return ArrayHelper::merge($rules, $parentRules);
}
/**
* {@inheritdoc}
* @return PageQuery the active query used by this AR class.
*/
public static function find()
{
return new PageQuery(get_called_class());
}
}
24. Edit \rpc\config\main.php to support internationalization
'i18n' => [
'translations' => [
'model/*'=> [
'class' => 'yii\i18n\PhpMessageSource',
'forceTranslation' => true,
'basePath'=>'@common/messages',
'fileMap'=>[
],
],
'*'=> [
'class' => 'yii\i18n\PhpMessageSource',
'forceTranslation' => true,
'basePath'=>'@rpc/messages',
'fileMap'=>[
],
],
],
],
],
25. Edit \api\rests\page\createaction.php
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace api\rests\page;
use Yii;
use yii\base\Model;
use yii\helpers\Url;
use yii\web\ServerErrorHttpException;
/**
* CreateAction implements 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 scenario 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';
public $createScenario = 'create';
/**
* Creates a new model.
* @return \yii\db\ActiveRecordInterface 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);
}
/* @var $model \yii\db\ActiveRecord */
$model = new $this->modelClass([
'scenario' => $this->createScenario,
]);
$model->load(Yii::$app->getRequest()->getBodyParams(), '');
// 模型转换成数组
$data = $model->attributes;
// 内容协商
$response = Yii::$app->response;
$acceptParams = $response->acceptParams;
if (isset($acceptParams['version'])) {
$version = $acceptParams['version'];
} else {
$version = '';
}
if ($model->validate()) {
$data = $model->create($data, $version, Yii::$app->language);
if ($data['code'] === 10000) {
$response = Yii::$app->getResponse();
$response->setStatusCode(201);
$id = $data['data']['id'];
$response->getHeaders()->set('Location', Url::toRoute([$this->viewAction, 'id' => $id], true));
}
return $data;
} elseif ($model->hasErrors()) {
$response = Yii::$app->getResponse();
$response->setStatusCode(422, 'Data Validation Failed.');
foreach ($model->getFirstErrors() as $message) {
$firstErrors = $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.');
}
}
}
26. Edit \rpc\controllers\pagecontroller.php
<?php
/**
* Created by PhpStorm.
* User: WangQiang
* Date: 2018/08/01
* Time: 15:01
*/
namespace rpc\controllers;
use Yii;
use yii\web\ServerErrorHttpException;
/**
* Page Controller
*
* @author Qiang Wang <shuijingwanwq@163.com>
* @since 1.0
*/
class PageController extends ServerController
{
public $createScenario = 'create';
/**
* 创建页面
*
* @param array $data 数据
*
* @param string $version 版本号(次版本号与修订号)
* 格式如下:
* 2.3
*
* @param string $language 区域和语言
* 格式如下:
* en-US
*
* @return mixed
*/
public function actionCreate(array $data, string $version = '', string $language = '')
{
if (!empty($language)) {
Yii::$app->language = $language;
}
/* @var $model \yii\db\ActiveRecord */
$model = new $this->modelClass([
'scenario' => $this->createScenario,
]);
if ($model->load($data, '') && $model->save()) {
$data = $model->attributes;
} elseif ($model->hasErrors()) {
foreach ($model->getFirstErrors() as $message) {
$firstErrors = $message;
break;
}
return ['code' => 25004, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '25004'), ['firstErrors' => $firstErrors]))];
} elseif (!$model->hasErrors()) {
throw new ServerErrorHttpException('Failed to create the object for unknown reason1.');
}
return ['code' => 10000, 'message' => Yii::t('success', '15805'), 'data' => $data];
}
}
27. Postman in Postmanhttp://api.github-shuijingwan-yii2-app-advanced.localhost/v1/pages, the response failed
{
"title":"title-20180731-5"
}
Note: Interface model validation failed
{
"code": 20004,
"message": "数据验证失败:内容不能为空。"
}
28. Postman in Postmanhttp://api.github-shuijingwan-yii2-app-advanced.localhost/v1/pages, the response failed
{
"title":"title-20180731-5",
"body":"title-20180731-5",
"slug":"title-20180731-5"
}
Note: RPC model validation failed
{
"code": 25004,
"message": "数据验证失败:别名的值\"title-20180731-5\"已经被占用了。"
}
29. Postman in Postmanhttp://api.github-shuijingwan-yii2-app-advanced.localhost/v1/pages, respond to success
{
"title":"title-20180731-5",
"body":"title-20180731-5"
}
{
"code": 10000,
"message": "创建页面成功",
"data": {
"id": 12,
"slug": "title-20180731-5-7",
"title": "title-20180731-5",
"body": "title-20180731-5",
"view": 0,
"status": 1,
"created_at": 1533205467,
"updated_at": 1533205467
}
}

