在 Windwos 10、PHP 7.1.12 下 基于 Yii 2 Starter Kit,复制后台应用为接口应用,实现 RESTful Web 服务的流程
1、在 Windows PowerShll 中,进入 E:\wwwroot\cmcp-api 目录,如图1
2、新建应用api,复制backend目录为api,如图2
3、编辑 \.env.dist,新增 api 相关的配置,此为提交至Git版本控制的配置文件,如图3
1 2 3 4 | 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> |
4、编辑 \.env,新增 api 相关的配置,此为实际生效的配置文件,如图4
1 2 3 4 | 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> |
5、编辑 \common\config\bootstrap.php,配置接口应用的别名,如图5
1 2 | Yii::setAlias( '@api' , realpath (__DIR__. '/../../api' )); Yii::setAlias( '@apiUrl' , env( 'API_HOST_INFO' ) . env( 'API_BASE_URL' ) ); |
6、编辑 \common\config\base.php,配置接口应用的语言包文件,如图6
1 | 'api' => 'api.php' , |
7、新建接口应用的中文语言包文件,复制 \common\messages\zh\backend.php 为 \common\messages\zh\api.php(如果需要支持其他的语言,可以在其他的语言目录下新建),如图7
8、编辑 \common\config\base.php,配置接口应用的URL的解析与生成,如图8
1 2 3 4 5 6 7 | 'urlManagerApi' => \yii\helpers\ArrayHelper::merge( [ 'hostInfo' => env( 'API_HOST_INFO' ), 'baseUrl' => env( 'API_BASE_URL' ), ], require (Yii::getAlias( '@api/config/_urlManager.php' )) ), |
9、编辑 \console\controllers\AppController.php,搜索此文件有6处backend,则相应复制3份为api,如图9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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' , ]; |
10、编辑 \autocompletion.php,新增接口应用相关的配置,如图10
1 | * @property yii\web\UrlManager $urlManagerApi UrlManager for api application. |
11、在目录api中搜索backend\、backend/、=> ‘backend’、BACKEND,严格匹配大小写,将其分别替换为api\、api/、=> ‘api’、API,如图11
1 2 3 4 | backend\ 替换为: api\ backend/ 替换为: api/ => 'backend' 替换为: => 'api' BACKEND 替换为: => API |
12、在 \tests 目录中,还有相应的与新增接口应用相关的配置,此部分暂缓一下,到需要进行自动化测试的时候,再来进行配置了。查看 \api\web\index-test.php,如图12
13、在 Windows PowerShll 中,进入 E:\wwwroot\cmcp-api 目录,再次运行命令:php console/yii app/setup,设置可写、可执行权限,如图13
14、在 Nginx 配置文件中新增虚拟主机,重启Nginx,如图14
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | ## 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; } } |
15、在 hosts 文件中新增配置,如图15
1 2 | # 内容管控平台接口 127.0.0.1 cmcp-api.localhost www.cmcp-api.localhost frontend.cmcp-api.localhost backend.cmcp-api.localhost storage.cmcp-api.localhost |
16、打开 http://www.cmcp-api.localhost, 如果出现样式文件加载响应404的情况,可以删除 \api\web\assets 下的所有子目录,如图16
17、准备将创建页面的功能基于接口实现,如图17
18、调整 Page 模型的相关结构,实现模型分层,参考网址:http://www.shuijingwanwq.com/2017/08/15/1713/ ,如图18
19、打开网址:http://frontend.cmcp-api.localhost/gii ,如图19
20、基于数据库表 ca_page 建立相应模型,如图20
21、在common目录中新建logics目录,用于MySQL模型的逻辑层所在目录,如图21
22、复制 \common\models\Page.php 至 \common\logics\Page.php,如图22
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <?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' ), ]; } } |
23、基于 diff ,编辑 \common\logics\Page.php,如图23
24、在common/logics目录中的MySQL模型文件为业务逻辑相关,继承至 \common\models\Page 数据层,如图24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <?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], ]; } } |
25、点击Model Generator下的Start按钮,生成模型Page,命名空间为common\models,此时需支持国际化,覆盖\common\models\Page.php,如图25
26、编辑 \common\config\base.php,当源语言和目标语言相同时,是否强制进行消息翻译,默认为假,设置为真,如图26
1 2 3 4 5 6 7 8 9 10 11 12 | '*' => [ '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' ] ], |
27、新建 \common\messages\en\model\page.php,支持目标语言为英语美国时的消息翻译,如图27
1 2 3 4 5 6 7 8 9 10 | return [ 'ID' => 'ID' , 'Slug' => 'Slug' , 'Title' => 'Title' , 'Body' => 'Body' , 'View' => 'Page View' , 'Status' => 'Active' , 'Created At' => 'Created At' , 'Updated At' => 'Updated At' , ]; |
28、新建 \common\messages\zh\model\page.php,支持目标语言为简体中文时的消息翻译,如图28
1 2 3 4 5 6 7 8 9 10 | return [ 'ID' => 'ID' , 'Slug' => '别名' , 'Title' => '标题' , 'Body' => '内容' , 'View' => '页面浏览' , 'Status' => '活动' , 'Created At' => '创建时间' , 'Updated At' => '更新时间' , ]; |
29、新建 \api\models\Page.php,在api/models目录中的MySQL模型文件为业务逻辑相关(仅与api相关),继承至 \common\logics\Page 逻辑层,如图29
30、复制\api\models\Page.php 至 \frontend\models\Page.php、\backend\models\Page.php,调整为各自的命名空间,如图30
31、在 api 应用中搜索 use common\models\Page;,替换为:use api\models\Page;,在前台、后台应用中同样类似处理,如图31
32、当本地设置为简体中文时,打开 http://backend.cmcp-api.localhost/page/create ,翻译功能可用,如图32
33、编辑个人信息,设置本地为英语美国,如图33
34、当本地设置为英语美国时,再次打开 http://backend.cmcp-api.localhost/page/create ,翻译功能可用,如图34
35、开始实现 RESTful Web 服务,参考网址:http://www.shuijingwanwq.com/2016/11/28/1457/ ,如图35
36、打开网址:http://backend.cmcp-api.localhost/article/create ,创建文章,如图36
37、在 Postman 中,GET http://frontend.cmcp-api.localhost/api/v1/articles ,此为自带的RESTful Web 服务,响应结果,如图37
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | { "items": [ { "id": 1, "slug": "biao-ti20180104-0", "category_id": 1, "title": "标题20180104-0", "body": " 内容 ", "published_at": 1515031309, "_links": { "self": { } } } ], "_links": { "self": { } }, "_meta": { "totalCount": 1, "pageCount": 1, "currentPage": 1, "perPage": 20 } } |
38、RESTful Web 服务,建议基于一个单独的接口应用来实现,而不是基于前台应用中的一个api模块来实现,这样可以更为方便地维护你的WEB应用程序,如图38
39、新建目录:\api\rests,此目录将做为 RESTful Web 服务的操作方法类目录,如图39
40、编辑控制器类 \api\controllers\PageController.php ,控制器类扩展自 [[yii\rest\ActiveController]]。 通过指定 [[yii\rest\ActiveController::modelClass|modelClass]] 作为 api\models\Page, 控制器就能知道使用哪个模型去获取和处理数据。如图40
1 2 3 4 5 6 7 8 | namespace api\controllers; use yii\rest\ActiveController; class PageController extends ActiveController { public $modelClass = 'api\models\Page' ; } |
41、配置URL规则,修改有关在应用程序配置的urlManager组件的配置,编辑:\api\config\_urlManager.php,如图41
1 2 3 4 5 6 7 8 9 10 11 | return [ 'class' => yii\web\UrlManager:: class , 'enablePrettyUrl' => true, 'showScriptName' => false, 'rules' => [ [ 'class' => 'yii\rest\UrlRule' , 'controller' => [ 'page' ], ], ], ]; |
42、在 Postman 中,GET http://www.cmcp-api.localhost/pages ,403响应,如图42
1 2 3 4 5 6 7 | { "name": "Forbidden", "message": "Login Required", "code": 0, "status": 403, "type": "yii\\web\\ForbiddenHttpException" } |
43、编辑 \api\config\web.php,注释附加的行为globalAccess,有待后期调整(验证、授权),如图43
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | /* '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'], ] ] ] */ |
44、在 Postman 中,GET http://www.cmcp-api.localhost/pages ,200响应,如图44
1 2 3 4 5 6 7 8 9 10 11 12 | [ { "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 } ] |
45、调用API服务后返回数据采用统一格式,返回的HTTP状态码为20x,代表调用成功;返回4xx或5xx的HTTP状态码代表调用失败。调整200响应的返回数据格式,与403响应一致,至少包含:”message”,”code”,新建语言包文件:\api\messages\zh\app.php(响应成功)、\api\messages\zh\error.php(响应失败),如图45
1 2 3 4 | return [ 10000 => 'success' , 10001 => '获取页面列表成功' , ]; |
46、版本化的实现,参考网址:https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/rest-versioning.md ,编辑 \api\controllers\PageController.php,删除 modelClass,如图46
1 2 3 4 5 6 7 8 9 | <?php namespace api\controllers; use yii\rest\ActiveController; class PageController extends ActiveController { } |
47、把每个主要版本的 API 实现在一个单独的模块 ID 的主版本号,基于 Gii 生成模块 v1,打开网址:http://frontend.cmcp-api.localhost/gii/module ,如图47
48、新建 \api\modules\v1\models\Page.php,继承至 \api\models\Page.php,如图48
注:\api\modules\v1\models\Page(仅用于 v1 模块) > \api\models\Page(仅用于 api 应用) > \common\logics\Page.php(可用于 api、frontend 等多个应用) > \common\models\Page.php(仅限于 Gii 生成) > \yii\db\ActiveRecord
1 2 3 4 5 6 7 8 | <?php namespace api\modules\v1\models; class Page extends \api\models\Page { } |
49、\api\modules\v1\controllers\DefaultController.php 重命名为 \api\modules\v1\controllers\PageController.php,编辑代码,如图49
注:\api\modules\v1\controllers\PageController.php(仅用于 v1 模块) > \api\controllers\PageController.php(仅用于 api 应用) > \yii\rest\ActiveController
1 2 3 4 5 6 7 8 9 10 11 | <?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' ; } |
50、要在应用中使用模块,只需要将模块加入到应用主体配置的[[yii\base\Application::modules|modules]]属性的列表中, 如下代码的应用主体配置 使用 v1 模块,编辑 \api\config\web.php,如图50
1 2 3 4 5 6 7 8 9 | 'modules' => [ 'v1' => [ 'class' => api\modules\v1\Module:: class , ], 'i18n' => [ 'class' => api\modules\i18n\Module:: class , 'defaultRoute' => 'i18n-message/index' ] ], |
注:通过配置 only 选项来明确列出哪些行为支持,v1/page 仅支持:’index’, ‘update’, ‘delete’, ‘options’
1 2 3 4 5 6 7 8 9 10 11 12 | <?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' ], ], ], ]; |
52、在 Postman 中,GET http://www.cmcp-api.localhost/v1/pages ,200响应,如图52
1 2 3 4 5 6 7 8 9 10 11 12 | [ { "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 } ] |
53、测试 only 选项,在 Postman 中,GET http://www.cmcp-api.localhost/v1/pages/1 ,405响应(不被允许的方法。因为 ‘view’ 行为不被支持),测试通过,如图53
54、配置URL规则,修改有关在应用程序配置的urlManager组件的配置,以支持 v1 模块,编辑:\api\config\_urlManager.php,如图54
注:取消配置 only 选项,以后续支持所有行为
1 2 3 4 5 6 7 8 9 10 11 | <?php return [ 'class' => yii\web\UrlManager:: class , 'enablePrettyUrl' => true, 'enableStrictParsing' => true, 'showScriptName' => false, 'rules' => [ [ 'class' => 'yii\rest\UrlRule' , 'controller' => [ 'v1/page' ], ], ], ]; |
55、在 Postman 中,GET http://www.cmcp-api.localhost/v1 ,404响应,格式为HMTL,如图55
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <! 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 > |
56、对于404响应格式为HTML的解决,编辑 \api\config\web.php,设置默认的响应格式为JSON,如图56
1 2 3 | 'response' => [ 'format' => yii\web\Response::FORMAT_JSON, ], |
57、在 Postman 中,GET http://www.cmcp-api.localhost/v1 ,404响应,格式为JSON,如图57
1 2 3 4 5 6 7 | { "name": "Not Found", "message": "Page not found.", "code": 0, "status": 404, "type": "yii\\web\\NotFoundHttpException" } |
58、数据序列化的实现,在响应主体内包含分页信息来简化客户端的开发工作,编辑 \api\controllers\PageController.php,如图58
1 2 3 4 | <?php namespace api\controllers; use yii\rest\ActiveController; class PageController extends ActiveController { public $serializer = [ 'class' => 'yii\rest\Serializer' , 'collectionEnvelope' => 'items' , ]; } |
59、在 Postman 中,GET http://www.cmcp-api.localhost/v1/pages ,200响应,在响应主体内包含分页信息,如图59
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | { "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": { } }, "_meta": { "totalCount": 1, "pageCount": 1, "currentPage": 1, "perPage": 20 } } |
60、RESTful APIs 通常是无状态的,因此,配置 user 应用组件,编辑 \api\config\web.php,如图60
注:配置user 应用组件:
设置 [[yii\web\User::enableSession|enableSession]] 属性为 false.
设置 [[yii\web\User::loginUrl|loginUrl]] 属性为null 显示一个HTTP 403 错误而不是跳转到登录界面.
1 2 3 4 5 6 7 8 | 'user' => [ 'class' => yii\web\User:: class , 'identityClass' => common\models\User:: class , 'enableSession' => false, 'loginUrl' => null, 'enableAutoLogin' => false, 'as afterLogin' => common\behaviors\LoginTimestampBehavior:: class ], |
61、复制目录 \vendor\yiisoft\yii2\rest 下的 Action.php、IndexAction.php、ViewAction.php、CreateAction.php、UpdateAction.php、DeleteAction.php、Serializer.php 至目录 \api\rests\page,如图61
62、如果为多个单词组合的目录,建议目录使用小写+下划线,参考网址:https://github.com/hfcorriez/fig-standards/blob/master/accepted/zh_CN/PSR-0.md ,编辑 \api\controllers\PageController.php,如图62
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | <?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' , ], ]; } } |
注:如果仅支持较少的行为,可以选择下面的方案,例
1 2 3 4 5 6 7 8 | public function actions() { $actions = parent::actions(); $actions [ 'view' ][ 'class' ] = 'api\rests\page\ViewAction' ; return $actions ; } |
63、编辑 \api\rests\page\IndexAction.php,调整命名空间、继承关系、查询条件等,如图63
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | <?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 , ], ]); } } |
64、编辑 \api\rests\page\Serializer.php,调整命名空间、继承关系、响应结构(响应成功:”code”: 10000,”message”,”data”;响应失败:”code”: 不等于10000的其他数字,”message”)等,如图64
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | <?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 ]; } } |
65、编辑 \api\config\base.php,配置接口应用的 i18n 应用组件 ,如图65
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | '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' =>[ ], ], ], ], |
66、新建语言包文件:\api\messages\zh\error.php(简体中文、响应失败),如图66
1 2 3 4 | return [ 20000 => 'error' , 20001 => '页面列表为空' , ]; |
67、新建语言包文件:\api\messages\en\app.php(英语美国、响应成功),如图67
1 2 3 4 | return [ 10000 => 'success' , 10001 => 'Get page list is successful' , ]; |
68、新建语言包文件:\api\messages\en\error.php(英语美国、响应失败),如图68
1 2 3 4 | return [ 20000 => 'error' , 20001 => 'Page list is empty' , ]; |
69、打开网址:http://backend.cmcp-api.localhost/page/update?id=1 ,编辑文章,活跃复选框取消选中,如图69
70、在 Postman 中,GET http://www.cmcp-api.localhost/v1/pages ,200响应,状态为活跃的页面列表为空,如图70
注:
Accept application/json; version=0.0
1 2 3 4 | { "code": 20001, "message": "Page list is empty" } |
71、在 Postman 中,GET http://www.cmcp-api.localhost/v1/pages ,200响应,状态为活跃的页面列表为空,如图71
注:
Accept application/json; version=0.0
Accept-Language zh-CN
1 2 3 4 | { "code": 20001, "message": "页面列表为空" } |
72、打开网址:http://backend.cmcp-api.localhost/page/update?id=1 ,编辑文章,活跃复选框勾选,如图72
73、在 Postman 中,GET http://www.cmcp-api.localhost/v1/pages ,200响应,状态为活跃的页面列表不为空,如图73
注:
Accept application/json; version=0.0
Accept-Language en-US
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | { "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": { } }, "_meta": { "totalCount": 1, "pageCount": 1, "currentPage": 1, "perPage": 20 } } } |
74、在 Postman 中,GET http://www.cmcp-api.localhost/v1/pages ,200响应,状态为活跃的页面列表不为空,如图74
注:
Accept application/json; version=0.0
Accept-Language zh-CN
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | { "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": { } }, "_meta": { "totalCount": 1, "pageCount": 1, "currentPage": 1, "perPage": 20 } } } |
75、GET /pages/1: 返回页面 1 的详细信息,编辑 \api\rests\page\Action.php,调整命名空间、继承关系、响应结构等,如图75
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | <?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); } } |
76、编辑 \api\rests\page\ViewAction.php,调整命名空间、继承关系、响应结构等,如图76
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | <?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 ]; } } |
77、编辑语言包文件:\api\messages\zh\app.php(简体中文、响应成功)、\api\messages\zh\error.php(简体中文、响应失败)、\api\messages\en\app.php(英语美国、响应成功)、\api\messages\en\error.php(英语美国、响应失败),如图77
\api\messages\zh\app.php
1 2 3 4 5 | return [ 10000 => 'success' , 10001 => '获取页面列表成功' , 10002 => '获取页面详情成功' , ]; |
\api\messages\zh\error.php
1 2 3 4 5 6 | return [ 20000 => 'error' , 20001 => '页面列表为空' , 20002 => '页面ID:{id},不存在' , 20003 => '页面ID:{id},的状态不活跃' , ]; |
\api\messages\en\app.php
1 2 3 4 5 | return [ 10000 => 'success' , 10001 => 'Get page list is successful' , 10002 => 'Get page details succeeded' , ]; |
\api\messages\en\error.php
1 2 3 4 5 6 | return [ 20000 => 'error' , 20001 => 'Page list is empty' , 20002 => 'Page ID: {id}, does not exist' , 20003 => 'Page ID: {id}, the status is not active' , ]; |
78、在 Postman 中,GET http://www.cmcp-api.localhost/v1/pages/1 ,200响应,其状态为活跃,如图78
注:
Accept application/json; version=0.0
Accept-Language zh-CN
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | { "code": 10000, "message": "获取页面详情成功", "data": { "id": 2, "slug": "contact", "title": "Contact", "body": " Contact ", "view": "", "status": 1, "created_at": 1515488912, "updated_at": 1515488912 } } |
79、在 Postman 中,GET http://www.cmcp-api.localhost/v1/pages/1 ,200响应,其状态为活跃,如图79
注:
Accept application/json; version=0.0
Accept-Language en-US
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | { "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 } } |
80、在 Postman 中,GET http://www.cmcp-api.localhost/v1/pages/2 ,200响应,其状态为不活跃,如图80
注:
Accept application/json; version=0.0
Accept-Language en-US
1 2 3 4 | { "code": 20003, "message": "Page ID: 2, the status is not active" } |
81、在 Postman 中,GET http://www.cmcp-api.localhost/v1/pages/3 ,404响应,页面不存在,如图81
注:
Accept application/json; version=0.0
Accept-Language zh-CN
1 2 3 4 5 6 7 | { "name": "Not Found", "message": "页面ID:3,不存在", "code": 20002, "status": 404, "type": "yii\\web\\NotFoundHttpException" } |
82、实现[[yii\web\Linkable]] 接口来支持HATEOAS,返回与本资源对象的相关链接,编辑资源类 \api\models\Page.php,如图82
1 2 3 4 5 6 7 8 9 10 11 | <?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), ]; } } |
注:
Accept application/json; version=0.0
Accept-Language zh-CN
Accept-Encoding gzip, deflate, br
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | { "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" } } } } |
84、POST /pages: 创建一个新页面,编辑 \api\rests\page\CreateAction.php,如图84
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | <?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 ]; } } |
85、在 Postman 中,POST http://www.cmcp-api.localhost/v1/pages ,201响应,如图85
注:
Accept application/json; version=0.0
Accept-Language zh-CN
Accept-Encoding gzip, deflate, br
Content-Type application/x-www-form-urlencoded
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | { "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" } } } } |
86、在 Postman 中,POST http://www.cmcp-api.localhost/v1/pages ,参数保持原样,422响应,如图86
注:
Accept application/json; version=0.0
Accept-Language zh-CN
Accept-Encoding gzip, deflate, br
Content-Type application/x-www-form-urlencoded
1 2 3 4 | { "code": 20004, "message": "数据验证失败:Slug的值\"slug-20180110-4\"已经被占用了。" } |
87、在 Postman 中,POST http://www.cmcp-api.localhost/v1/pages ,422响应(数据验证失败 (例如,响应一个 POST 请求)。 请检查响应体内详细的错误消息。),如图87
注:
Accept application/json; version=0.0
Accept-Language zh-CN
Accept-Encoding gzip, deflate, br
Content-Type application/x-www-form-urlencoded
Body
缺少 title 参数
1 2 3 4 | { "code": 20004, "message": "数据验证失败:Title不能为空。" } |
88、在 Postman 中,POST http://www.cmcp-api.localhost/v1/pages ,422响应,如图88
注:
Accept application/json; version=0.0
Accept-Language en-US
Accept-Encoding gzip, deflate, br
Content-Type application/x-www-form-urlencoded
Body
缺少 title 参数
1 2 3 4 | { "code": 20004, "message": "Data validation failed: Title cannot be blank." } |
89、PUT /pages/4: 更新一个页面,编辑 \api\rests\page\UpdateAction.php,如图89
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | <?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 ]; } } |
90、在 Postman 中,PUT http://www.cmcp-api.localhost/v1/pages/4 ,200响应,如图90
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | { "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" } } } } |
91、在 Postman 中,PUT http://www.cmcp-api.localhost/v1/pages/4 ,422响应,如图91
注:
Accept application/json; version=0.0
Accept-Language en-US
Accept-Encoding gzip, deflate, br
Content-Type application/x-www-form-urlencoded
Body
slug 的值已经被另一页面占用
1 2 3 4 | { "code": 20004, "message": "Data validation failed: Slug \"slug-20180110-5\" has already been taken." } |
92、DELETE /pages/4: 删除页面4,编辑 \api\rests\page\DeleteAction.php,如图92
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <?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' )]; } } |
93、在 Postman 中,DELETE http://www.cmcp-api.localhost/v1/pages/7 ,200响应,如图93
注:
Accept application/json; version=0.0
Accept-Language zh-CN
Accept-Encoding gzip, deflate, br
1 2 3 4 | { "code": 10000, "message": "删除页面成功" } |
94、展示一下语言包文件的最后内容,如图94
\api\messages\zh\app.php
1 2 3 4 5 6 7 8 | return [ 10000 => 'success' , 10001 => '获取页面列表成功' , 10002 => '获取页面详情成功' , 10003 => '创建页面成功' , 10004 => '更新页面成功' , 10005 => '删除页面成功' , ]; |
\api\messages\zh\error.php
1 2 3 4 5 6 7 | return [ 20000 => 'error' , 20001 => '页面列表为空' , 20002 => '页面ID:{id},不存在' , 20003 => '页面ID:{id},的状态不活跃' , 20004 => '数据验证失败:{firstErrors}' , ]; |
\api\messages\en\app.php
1 2 3 4 5 6 7 8 | 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' , ]; |
\api\messages\en\error.php
1 2 3 4 5 6 7 | 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}' , ]; |
95、OPTIONS /pages: 显示关于末端 /pages 支持的动词,在 Postman 中,OPTIONS http://www.cmcp-api.localhost/v1/pages ,200响应,如图95
96、OPTIONS /pages/1: 显示关于末端 /pages/1 支持的动词,在 Postman 中,OPTIONS http://www.cmcp-api.localhost/v1/pages/1 ,200响应,如图96
97、总结:现在支持的行为:index、view、create、update、delete、options,除 options 之外,基本上是继承之后,再次覆写实现具体的需求了的。
1 条回复
[…] […]