

<pre class="wp-block-syntaxhighlighter-code">
API_HOST_INFO = http://api.yii2-starter-kit.dev
#API_HOST_INFO = http://yii2-starter-kit.dev
#API_BASE_URL = /api/web
API_COOKIE_VALIDATION_KEY = <generated_key>
</pre>

<pre class="wp-block-syntaxhighlighter-code">
API_HOST_INFO = http://www.cmcp-api.localhost
#API_HOST_INFO = http://yii2-starter-kit.dev
#API_BASE_URL = /api/web
API_COOKIE_VALIDATION_KEY = <generated_key>
</pre>

Yii::setAlias('@api', realpath(__DIR__.'/../../api'));
Yii::setAlias('@apiUrl', env('API_HOST_INFO') . env('API_BASE_URL') );

'api'=>'api.php',


'urlManagerApi' => \yii\helpers\ArrayHelper::merge(
[
'hostInfo' => env('API_HOST_INFO'),
'baseUrl' => env('API_BASE_URL'),
],
require(Yii::getAlias('@api/config/_urlManager.php'))
),

public $writablePaths = [
'@common/runtime',
'@frontend/runtime',
'@frontend/web/assets',
'@backend/runtime',
'@backend/web/assets',
'@api/runtime',
'@api/web/assets',
'@storage/cache',
'@storage/web/source'
];
public $executablePaths = [
'@backend/yii',
'@api/yii',
'@frontend/yii',
'@console/yii',
];

* @property yii\web\UrlManager $urlManagerApi UrlManager for api application.

backend\ 替换为: api\
backend/ 替换为: api/
=> 'backend' 替换为: => 'api'
BACKEND 替换为: => API



## API ##
server {
listen 80; ## 监听 ipv4 上的 80 端口
# listen [::]:80 default_server ipv6only=on; ## 监听 ipv6 上的 80 端口
root E:/wwwroot/cmcp-api/api/web;
index index.php index.html;
server_name www.cmcp-api.localhost;
charset utf-8;
access_log logs/www.cmcp-api.localhost.access.log;
error_log logs/www.cmcp-api.localhost.error.log;
client_max_body_size 128M;
# There is a VirtualBox bug related to sendfile that can lead to
# corrupted files, if not turned-off on Vagrant based setup
# sendfile off;
location / {
# 如果找不到真实存在的文件,把请求分发至 index.php
try_files $uri $uri/ /index.php?$args;
}
# location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|pdf|ppt|txt|bmp|rtf|js)$ {
# access_log off;
# expires max;
# }
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass php-fpm;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ /\.(ht|svn|git) {
deny all;
}
}

# 内容管控平台接口
127.0.0.1 cmcp-api.localhost www.cmcp-api.localhost frontend.cmcp-api.localhost backend.cmcp-api.localhost storage.cmcp-api.localhost







<pre class="wp-block-syntaxhighlighter-code">
<?php namespace common\models; use Yii; use yii\behaviors\SluggableBehavior; use yii\behaviors\TimestampBehavior; use yii\db\ActiveRecord; /** * This is the model class for table "page". * * @property integer $id * @property string $slug * @property string $title * @property string $body * @property string $view * @property integer $status * @property integer $created_at * @property integer $updated_at */ class Page extends ActiveRecord { const STATUS_DRAFT = 0; const STATUS_PUBLISHED = 1; /** * @inheritdoc */ public static function tableName() { return '{{%page}}'; } /** * @inheritdoc */ public function behaviors() { return [ TimestampBehavior::className(), 'slug' => [
'class' => SluggableBehavior::className(),
'attribute' => 'title',
'ensureUnique' => true,
'immutable' => true
]
];
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['title', 'body'], 'required'],
[['body'], 'string'],
[['status'], 'integer'],
[['slug'], 'unique'],
[['slug'], 'string', 'max' => 2048],
[['title'], 'string', 'max' => 512],
[['view'], 'string', 'max' => 255]
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => Yii::t('common', 'ID'),
'slug' => Yii::t('common', 'Slug'),
'title' => Yii::t('common', 'Title'),
'body' => Yii::t('common', 'Body'),
'view' => Yii::t('common', 'Page View'),
'status' => Yii::t('common', 'Active'),
'created_at' => Yii::t('common', 'Created At'),
'updated_at' => Yii::t('common', 'Updated At'),
];
}
}
</pre>


<pre class="wp-block-syntaxhighlighter-code">
<?php namespace common\logics; use Yii; use yii\behaviors\SluggableBehavior; use yii\behaviors\TimestampBehavior; class Page extends \common\models\Page { const STATUS_DRAFT = 0; const STATUS_PUBLISHED = 1; /** * @inheritdoc */ public function behaviors() { return [ TimestampBehavior::className(), 'slug' => [
'class' => SluggableBehavior::className(),
'attribute' => 'title',
'ensureUnique' => true,
'immutable' => true
]
];
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['title', 'body'], 'required'],
[['body'], 'string'],
[['status'], 'integer'],
[['slug'], 'unique'],
[['slug'], 'string', 'max' => 2048],
[['title'], 'string', 'max' => 512],
[['view'], 'string', 'max' => 255],
];
}
}
</pre>


'*'=> [
'class' => 'yii\i18n\PhpMessageSource',
'forceTranslation' => true,
'basePath'=>'@common/messages',
'fileMap'=>[
'common'=>'common.php',
'backend'=>'backend.php',
'api'=>'api.php',
'frontend'=>'frontend.php',
],
'on missingTranslation' => ['\backend\modules\i18n\Module', 'missingTranslation']
],

return [
'ID' => 'ID',
'Slug' => 'Slug',
'Title' => 'Title',
'Body' => 'Body',
'View' => 'Page View',
'Status' => 'Active',
'Created At' => 'Created At',
'Updated At' => 'Updated At',
];

return [
'ID' => 'ID',
'Slug' => '别名',
'Title' => '标题',
'Body' => '内容',
'View' => '页面浏览',
'Status' => '活动',
'Created At' => '创建时间',
'Updated At' => '更新时间',
];









{
"items": [
{
"id": 1,
"slug": "biao-ti20180104-0",
"category_id": 1,
"title": "标题20180104-0",
"body": "
内容
",
"published_at": 1515031309,
"_links": {
"self": {
"href": "http://frontend.cmcp-api.localhost/api/v1/articles/1"
}
}
}
],
"_links": {
"self": {
"href": "http://frontend.cmcp-api.localhost/api/v1/articles?page=1"
}
},
"_meta": {
"totalCount": 1,
"pageCount": 1,
"currentPage": 1,
"perPage": 20
}
}



namespace api\controllers;
use yii\rest\ActiveController;
class PageController extends ActiveController
{
public $modelClass = 'api\models\Page';
}
![编辑控制器类 \api\controllers\PageController.php ,控制器类扩展自 [[yii\rest\ActiveController]]。 通过指定 [[yii\rest\ActiveController::modelClass|modelClass]] 作为 api\models\Page, 控制器就能知道使用哪个模型去获取和处理数据。](https://media.shuijingwanwq.com/2018/01/40.png)
return [
'class' => yii\web\UrlManager::class,
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => ['page'],
],
],
];

{
"name": "Forbidden",
"message": "Login Required",
"code": 0,
"status": 403,
"type": "yii\\web\\ForbiddenHttpException"
}

/*
'as globalAccess' => [
'class' => common\behaviors\GlobalAccessBehavior::class,
'rules' => [
[
'controllers' => ['sign-in'],
'allow' => true,
'roles' => ['?'],
'actions' => ['login']
],
[
'controllers' => ['sign-in'],
'allow' => true,
'roles' => ['@'],
'actions' => ['logout']
],
[
'controllers' => ['site'],
'allow' => true,
'roles' => ['?', '@'],
'actions' => ['error']
],
[
'controllers' => ['debug/default'],
'allow' => true,
'roles' => ['?'],
],
[
'controllers' => ['user'],
'allow' => true,
'roles' => ['administrator'],
],
[
'controllers' => ['user'],
'allow' => false,
],
[
'allow' => true,
'roles' => ['manager'],
]
]
]
*/

[
{
"id": 1,
"slug": "about",
"title": "About",
"body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
"view": null,
"status": 1,
"created_at": 1514860785,
"updated_at": 1514860785
}
]

return [
10000 => 'success',
10001 => '获取页面列表成功',
];

<pre class="wp-block-syntaxhighlighter-code">
<?php
namespace api\controllers;
use yii\rest\ActiveController;
class PageController extends ActiveController
{
}
</pre>


<pre class="wp-block-syntaxhighlighter-code">
<?php
namespace api\modules\v1\models;
class Page extends \api\models\Page
{
}
</pre>

<pre class="wp-block-syntaxhighlighter-code">
<?php
namespace api\modules\v1\controllers;
/**
* Page controller for the `v1` module
*/
class PageController extends \api\controllers\PageController
{
public $modelClass = 'api\modules\v1\models\Page';
}
</pre>

'modules' => [
'v1' => [
'class' => api\modules\v1\Module::class,
],
'i18n' => [
'class' => api\modules\i18n\Module::class,
'defaultRoute' => 'i18n-message/index'
]
],
![要在应用中使用模块,只需要将模块加入到应用主体配置的[[yii\base\Application::modules|modules]]属性的列表中, 如下代码的应用主体配置 使用 v1 模块,编辑 \api\config\web.php](https://media.shuijingwanwq.com/2018/01/50.png)
<pre class="wp-block-syntaxhighlighter-code">
<?php return [ 'class' => yii\web\UrlManager::class,
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => ['v1/page'],
'only' => ['index', 'update', 'delete', 'options'],
],
],
];
</pre>

[
{
"id": 1,
"slug": "about",
"title": "About",
"body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
"view": null,
"status": 1,
"created_at": 1514860785,
"updated_at": 1514860785
}
]


<pre class="wp-block-syntaxhighlighter-code">
<?php return [ 'class' => yii\web\UrlManager::class,
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => ['v1/page'],
],
],
];
</pre>

<pre class="wp-block-syntaxhighlighter-code">
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
<meta name="csrf-param" content="_csrf">
<meta name="csrf-token" content="MtUm8pVxEHfmqhYMruxdUyScsktaMyFDc350jW_XR7dzmGqaoDRyT7bPc13M2W0AVNuGISJSbQUYOFn9LKNzgQ==">
<title>Not Found (#404)</title>
<link href="/assets/95b60493/themes/smoothness/jquery-ui.css?v=1514958071" rel="stylesheet">
<link href="/assets/7635f0fe/css/bootstrap.css?v=1512021376" rel="stylesheet">
<link href="/assets/1ee3df8/css/font-awesome.min.css?v=1512021376" rel="stylesheet">
<link href="/assets/541f775b/css/AdminLTE.min.css?v=1512021373" rel="stylesheet">
<link href="/assets/541f775b/css/skins/_all-skins.min.css?v=1512021373" rel="stylesheet">
<link href="/css/style.css?v=1512021342" rel="stylesheet">
</head>
<body class=" skin-blue ">
</body>
</html>
</pre>

'response' => [
'format' => yii\web\Response::FORMAT_JSON,
],

{
"name": "Not Found",
"message": "Page not found.",
"code": 0,
"status": 404,
"type": "yii\\web\\NotFoundHttpException"
}

<pre class="wp-block-syntaxhighlighter-code">
<?php namespace api\controllers; use yii\rest\ActiveController; class PageController extends ActiveController { public $serializer = [ 'class' => 'yii\rest\Serializer',
'collectionEnvelope' => 'items',
];
}
</pre>

{
"items": [
{
"id": 1,
"slug": "about",
"title": "About",
"body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
"view": null,
"status": 1,
"created_at": 1514860785,
"updated_at": 1514860785
}
],
"_links": {
"self": {
"href": "http://www.cmcp-api.localhost/v1/pages?page=1"
}
},
"_meta": {
"totalCount": 1,
"pageCount": 1,
"currentPage": 1,
"perPage": 20
}
}

'user' => [
'class' => yii\web\User::class,
'identityClass' => common\models\User::class,
'enableSession' => false,
'loginUrl' => null,
'enableAutoLogin' => false,
'as afterLogin' => common\behaviors\LoginTimestampBehavior::class
],


<pre class="wp-block-syntaxhighlighter-code">
<?php namespace api\controllers; use yii\rest\ActiveController; class PageController extends ActiveController { public $serializer = [ 'class' => 'api\rests\page\Serializer',
'collectionEnvelope' => 'items',
];
/**
* @inheritdoc
*/
public function actions()
{
return [
'index' => [
'class' => 'api\rests\page\IndexAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
],
'view' => [
'class' => 'api\rests\page\ViewAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
],
'create' => [
'class' => 'api\rests\page\CreateAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
'scenario' => $this->createScenario,
],
'update' => [
'class' => 'api\rests\page\UpdateAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
'scenario' => $this->updateScenario,
],
'delete' => [
'class' => 'api\rests\page\DeleteAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
],
'options' => [
'class' => 'yii\rest\OptionsAction',
],
];
}
}
</pre>
public function actions()
{
$actions = parent::actions();
$actions['view']['class'] = 'api\rests\page\ViewAction';
return $actions;
}

<pre class="wp-block-syntaxhighlighter-code">
<?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\data\ActiveDataProvider;
/**
* IndexAction implements 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_INACTIVE = 0; //状态:不活跃
const STATUS_ACTIVE = 1; //状态:活跃
/**
* 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->prepareDataProvider, $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,
],
'sort' => [
'params' => $requestParams,
],
]);
}
}
</pre>

<pre class="wp-block-syntaxhighlighter-code">
<?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\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
* implementing [[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 serializeDataProvider($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->getIsHead()) {
return null;
} elseif ($this->collectionEnvelope === null) {
return $models;
}
$result = [
$this->collectionEnvelope => $models,
];
if (empty($result['items'])) {
return ['code' => 20001, 'message' => Yii::t('error', '20001')];
}
if ($pagination !== false) {
return ['code' => 10000, 'message' => Yii::t('app', '10001'), 'data' => array_merge($result, $this->serializePagination($pagination))];
}
return ['code' => 10000, 'message' => Yii::t('app', '10001'), 'data' => $result];
}
}
</pre>

'i18n' => [
'translations' => [
'model/*'=> [
'class' => 'yii\i18n\PhpMessageSource',
'forceTranslation' => true,
'basePath'=>'@common/messages',
'fileMap'=>[
],
],
'app'=> [
'class' => 'yii\i18n\PhpMessageSource',
'forceTranslation' => true,
'basePath'=>'@api/messages',
'fileMap'=>[
],
],
'*'=> [
'class' => 'yii\i18n\PhpMessageSource',
'forceTranslation' => true,
'basePath'=>'@api/messages',
'fileMap'=>[
],
],
],
],

return [
20000 => 'error',
20001 => '页面列表为空',
];

return [
10000 => 'success',
10001 => 'Get page list is successful',
];

return [
20000 => 'error',
20001 => 'Page list is empty',
];


{
"code": 20001,
"message": "Page list is empty"
}

{
"code": 20001,
"message": "页面列表为空"
}


{
"code": 10000,
"message": "Get page list is successful",
"data": {
"items": [
{
"id": 1,
"slug": "about",
"title": "About",
"body": "
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
",
"view": "",
"status": 1,
"created_at": 1514860785,
"updated_at": 1515482758
}
],
"_links": {
"self": {
"href": "http://www.cmcp-api.localhost/v1/pages?page=1"
}
},
"_meta": {
"totalCount": 1,
"pageCount": 1,
"currentPage": 1,
"perPage": 20
}
}
}

{
"code": 10000,
"message": "获取页面列表成功",
"data": {
"items": [
{
"id": 1,
"slug": "about",
"title": "About",
"body": "
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
",
"view": "",
"status": 1,
"created_at": 1514860785,
"updated_at": 1515482758
}
],
"_links": {
"self": {
"href": "http://www.cmcp-api.localhost/v1/pages?page=1"
}
},
"_meta": {
"totalCount": 1,
"pageCount": 1,
"currentPage": 1,
"perPage": 20
}
}
}

<pre class="wp-block-syntaxhighlighter-code">
<?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\db\ActiveRecordInterface;
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
{
/**
* Returns 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. If the model has a composite primary key,
* 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 = explode(',', $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);
}
}
</pre>

<pre class="wp-block-syntaxhighlighter-code">
<?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;
/**
* ViewAction implements the API endpoint for returning the detailed information about a model.
*
* For more details and usage information on ViewAction, 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_INACTIVE = 0; //状态:不活跃
const STATUS_ACTIVE = 1; //状态:活跃
/**
* Displays a model.
* @param string $id the primary key of the model.
* @return \yii\db\ActiveRecordInterface the model being displayed
*/
public function run($id)
{
$model = $this->findModel($id);
if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id, $model);
}
/* 判断状态,如果为不活跃,则返回失败 */
if ($model->status === self::STATUS_INACTIVE) {
return ['code' => 20003, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '20003'), ['id' => $id]))];
}
return ['code' => 10000, 'message' => Yii::t('app', '10002'), 'data' => $model];
}
}
</pre>

return [
10000 => 'success',
10001 => '获取页面列表成功',
10002 => '获取页面详情成功',
];
return [
20000 => 'error',
20001 => '页面列表为空',
20002 => '页面ID:{id},不存在',
20003 => '页面ID:{id},的状态不活跃',
];
return [
10000 => 'success',
10001 => 'Get page list is successful',
10002 => 'Get page details succeeded',
];
return [
20000 => 'error',
20001 => 'Page list is empty',
20002 => 'Page ID: {id}, does not exist',
20003 => 'Page ID: {id}, the status is not active',
];

{
"code": 10000,
"message": "获取页面详情成功",
"data": {
"id": 2,
"slug": "contact",
"title": "Contact",
"body": "
Contact
",
"view": "",
"status": 1,
"created_at": 1515488912,
"updated_at": 1515488912
}
}

{
"code": 10000,
"message": "Get page details succeeded",
"data": {
"id": 2,
"slug": "contact",
"title": "Contact",
"body": "
Contact
",
"view": "",
"status": 1,
"created_at": 1515488912,
"updated_at": 1515488912
}
}

{
"code": 20003,
"message": "Page ID: 2, the status is not active"
}

{
"name": "Not Found",
"message": "页面ID:3,不存在",
"code": 20002,
"status": 404,
"type": "yii\\web\\NotFoundHttpException"
}

<pre class="wp-block-syntaxhighlighter-code">
<?php namespace api\models; use yii\helpers\Url; use yii\web\Linkable; use yii\web\Link; class Page extends \common\logics\Page implements Linkable { /** * Returns a list of links. * * @return array the links */ public function getLinks() { return [ Link::REL_SELF => Url::to(['page/view', 'id' => $this->id], true),
'index' => Url::to(['page/index'], true),
'view' => Url::to(['page/view', 'id' => $this->id], true),
'create' => Url::to(['page/index'], true),
'update' => Url::to(['page/view', 'id' => $this->id], true),
'delete' => Url::to(['page/view', 'id' => $this->id], true),
'options' => Url::to(['page/index'], true),
];
}
}
</pre>
![实现[[yii\web\Linkable]] 接口来支持HATEOAS,返回与本资源对象的相关链接,编辑资源类 \api\models\Page.php](https://media.shuijingwanwq.com/2018/01/82.png)
{
"code": 10000,
"message": "获取页面详情成功",
"data": {
"id": 1,
"slug": "about",
"title": "About",
"body": "
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
",
"view": "",
"status": 1,
"created_at": 1514860785,
"updated_at": 1515548927,
"_links": {
"self": {
"href": "http://www.cmcp-api.localhost/v1/pages/1"
},
"index": {
"href": "http://www.cmcp-api.localhost/v1/pages"
},
"view": {
"href": "http://www.cmcp-api.localhost/v1/pages/1"
},
"create": {
"href": "http://www.cmcp-api.localhost/v1/pages"
},
"update": {
"href": "http://www.cmcp-api.localhost/v1/pages/1"
},
"delete": {
"href": "http://www.cmcp-api.localhost/v1/pages/1"
},
"options": {
"href": "http://www.cmcp-api.localhost/v1/pages"
}
}
}
}

<pre class="wp-block-syntaxhighlighter-code">
<?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';
/**
* 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->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;
}
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('app', '10003'), 'data' => $model];
}
}
</pre>

{
"code": 10000,
"message": "创建页面成功",
"data": {
"slug": "slug-20180110-4",
"title": "title-20180110-4",
"body": "body-20180110-4",
"view": "view-20180110-4",
"status": "0",
"created_at": 1515566824,
"updated_at": 1515566824,
"id": 7,
"_links": {
"self": {
"href": "http://www.cmcp-api.localhost/v1/pages/7"
},
"index": {
"href": "http://www.cmcp-api.localhost/v1/pages"
},
"view": {
"href": "http://www.cmcp-api.localhost/v1/pages/7"
},
"create": {
"href": "http://www.cmcp-api.localhost/v1/pages"
},
"update": {
"href": "http://www.cmcp-api.localhost/v1/pages/7"
},
"delete": {
"href": "http://www.cmcp-api.localhost/v1/pages/7"
},
"options": {
"href": "http://www.cmcp-api.localhost/v1/pages"
}
}
}
}

{
"code": 20004,
"message": "数据验证失败:Slug的值\"slug-20180110-4\"已经被占用了。"
}

{
"code": 20004,
"message": "数据验证失败:Title不能为空。"
}

{
"code": 20004,
"message": "Data validation failed: Title cannot be blank."
}

<pre class="wp-block-syntaxhighlighter-code">
<?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\db\ActiveRecord;
use yii\web\ServerErrorHttpException;
/**
* UpdateAction implements 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);
}
$model->scenario = $this->scenario;
$model->load(Yii::$app->getRequest()->getBodyParams(), '');
if ($model->save() === false) {
if ($model->hasErrors()) {
$response = Yii::$app->getResponse();
$response->setStatusCode(422, 'Data Validation Failed.');
foreach ($model->getFirstErrors() as $message) {
$firstErrors = $message;
}
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('app', '10004'), 'data' => $model];
}
}
</pre>

{
"code": 10000,
"message": "更新页面成功",
"data": {
"id": 4,
"slug": "slug-20180110-44",
"title": "title-20180110-44",
"body": "body-20180110-44",
"view": "view-20180110-44",
"status": "1",
"created_at": 1515554512,
"updated_at": 1515569633,
"_links": {
"self": {
"href": "http://www.cmcp-api.localhost/v1/pages/4"
},
"index": {
"href": "http://www.cmcp-api.localhost/v1/pages"
},
"view": {
"href": "http://www.cmcp-api.localhost/v1/pages/4"
},
"create": {
"href": "http://www.cmcp-api.localhost/v1/pages"
},
"update": {
"href": "http://www.cmcp-api.localhost/v1/pages/4"
},
"delete": {
"href": "http://www.cmcp-api.localhost/v1/pages/4"
},
"options": {
"href": "http://www.cmcp-api.localhost/v1/pages"
}
}
}
}

{
"code": 20004,
"message": "Data validation failed: Slug \"slug-20180110-5\" has already been taken."
}

<pre class="wp-block-syntaxhighlighter-code">
<?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\web\ServerErrorHttpException;
/**
* DeleteAction implements 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('app', '10005')];
}
}
</pre>

{
"code": 10000,
"message": "删除页面成功"
}

return [
10000 => 'success',
10001 => '获取页面列表成功',
10002 => '获取页面详情成功',
10003 => '创建页面成功',
10004 => '更新页面成功',
10005 => '删除页面成功',
];
return [
20000 => 'error',
20001 => '页面列表为空',
20002 => '页面ID:{id},不存在',
20003 => '页面ID:{id},的状态不活跃',
20004 => '数据验证失败:{firstErrors}',
];
return [
10000 => 'success',
10001 => 'Get page list is successful',
10002 => 'Get page details succeeded',
10003 => 'Create a page success',
10004 => 'Update page success',
10005 => 'Delete page success',
];
return [
20000 => 'error',
20001 => 'Page list is empty',
20002 => 'Page ID: {id}, does not exist',
20003 => 'Page ID: {id}, the status is not active',
20004 => 'Data validation failed: {firstErrors}',
];



PHP / Laravel / Yii2 老项目维护与长期技术支持
如果你的 PHP / Laravel / Yii2 项目已经上线,但遇到原开发离职、Bug 长期无人修复、接口不稳定、性能下降、代码难以接手等问题,可以联系我做一次远程技术排查。
适合以下情况:
✅ 老旧 PHP 系统无人维护
✅ Laravel / Yii2 项目 Bug 修复
✅ 后台管理系统小功能迭代
✅ RESTful API 接口排查
✅ MySQL / Redis / Nginx 性能问题
✅ 长期远程兼职维护
可先从一次小问题开始:
✅ 线上报错排查
✅ 接口异常分析
✅ 慢查询与性能瓶颈定位
✅ 代码结构初步评估
✅ 部署环境与日志检查
如需咨询,请联系我,并注明:PHP 维护咨询。
联系方式:
Telegram:@shuijingwan
微信:13980074657
邮箱:shuijingwanwq@gmail.com

发表回复