在 Windwos 10 下 基于 Yii2 高级应用模板,实现 RESTful Web 服务的流程
1、请先参考上一篇博客:http://www.shuijingwanwq.com/2016/11/26/1436/
2、准备基于 shujujiexi 实现 RESTful Web 服务
3、基于 frontend 应用上的 Gii 生成模型,编辑\environments\dev\frontend\config\main-local.php,如图1
1 2 3 4 5 | $config [ 'bootstrap' ][] = 'gii' ; $config [ 'modules' ][ 'gii' ] = [ 'class' => 'yii\gii\Module' , 'allowedIPs' => [ '127.0.0.1' , '::1' ], ]; |
4、在 Windows PowerShell 中执行 .\init,以覆盖\frontend\config\main-local.php,设置 Gii 允许访问的IP,如图2
5、打开网址:http://www.kaiqiu_shujujiexi_api.dev/index.php?r=gii,可以访问 Gii 了,如图3
6、编辑\frontend\config\main.php,以支持网址美化,如图4
1 2 3 4 5 6 | 'urlManager' => [ 'enablePrettyUrl' => true, 'showScriptName' => false, 'rules' => [ ], ], |
7、打开网址:http://www.kaiqiu_shujujiexi_api.dev/gii,如图5
8、基于数据库表kq_schedule建立相应模型,如图6
9、点击Model Generator下的Start按钮,生成模型Schedule,命名空间为common\models,以便于后期其他应用皆可以使用此模型,此时无需支持国际化,如图7
10、点击 Generate 按钮,生成模型文件\common\models\Schedule.php,如图8
11、创建一个控制器\shujujiexi\controllers\ScheduleController.php,如图9
1 2 3 4 5 6 7 8 9 10 11 | <?php namespace shujujiexi\controllers; use yii\rest\ActiveController; class ScheduleController extends ActiveController { public $modelClass = 'common\models\Schedule' ; } |
12、配置URL规则,修改urlManager组件的配置,如图10
1 2 3 4 5 6 7 8 9 10 11 | 'urlManager' => [ 'enablePrettyUrl' => true, 'enableStrictParsing' => true, 'showScriptName' => false, 'rules' => [ [ 'class' => 'yii\rest\UrlRule' , 'controller' => 'schedule' , ], ], ], |
13、在Postman中GET:shujujiexi.kaiqiu_shujujiexi_api.dev/schedules,正确响应,如图11
14、为了在shujujiexi应用中实现自身的业务逻辑,建议新建\shujujiexi\models\Schedule.php,其继承至\common\models\Schedule,如图12
15、编辑控制器\shujujiexi\controllers\ScheduleController.php,重新指定模型为shujujiexi\models\Schedule,如图13
16、在Postman中GET:shujujiexi.kaiqiu_shujujiexi_api.dev/schedules,正确响应,如图11
17、在Postman中PUT:shujujiexi.kaiqiu_shujujiexi_api.dev/schedules/1,正确响应,如图14
18、配置 only 和 except 选项来明确列出哪些行为支持, 哪些行为禁用。例如,只让其支持GET列表,则可以修改urlManager组件的配置,如图15
1 2 3 4 5 6 7 8 9 10 11 12 | 'urlManager' => [ 'enablePrettyUrl' => true, 'enableStrictParsing' => true, 'showScriptName' => false, 'rules' => [ [ 'class' => 'yii\rest\UrlRule' , 'controller' => 'schedule' , 'only' => [ 'index' ], ], ], ], |
19、在Postman中PUT:shujujiexi.kaiqiu_shujujiexi_api.dev/schedules/1,404响应,如图16
20、基于URL规则:’GET,HEAD users’ => ‘user/index’,,在Postman中HEAD:shujujiexi.kaiqiu_shujujiexi_api.dev/schedules,空响应,可以不用理会,其他请求皆为404,如图17
21、对于404响应格式为HTML的解决,编辑\shujujiexi\config\main.php,设置默认的响应格式为JSON,如图18
1 2 3 | 'response' => [ 'format' => yii\web\Response::FORMAT_JSON, ], |
22、再次执行第19项,404响应,其格式为JSON,如图19
23、数据序列化的实现,在响应主体内包含分页信息来 简化客户端的开发工作,编辑\shujujiexi\controllers\ScheduleController.php,如图20
1 2 3 4 | public $serializer = [ 'class' => 'yii\rest\Serializer' , 'collectionEnvelope' => 'items' , ]; |
24、在Postman中GET:shujujiexi.kaiqiu_shujujiexi_api.dev/schedules,正确响应,在响应主体内包含分页信息,如图21
25、RESTful APIs 通常是无状态的,因此,配置user 应用组件,编辑\shujujiexi\config\main.php,如图22
1 2 3 4 5 6 7 | 'user' => [ 'identityClass' => 'common\models\User' , 'enableAutoLogin' => false, 'identityCookie' => [ 'name' => '_identity-shujujiexi' , 'httpOnly' => true], 'enableSession' => false, 'loginUrl' => null, ], |
26、版本化的实现,新建目录\shujujiexi\modules,其结构如图23
27、\shujujiexi\modules\v1\Module.php,其内容,如图24
28、\shujujiexi\modules\v1\controllers\ScheduleController.php,其内容,如图25
29、\shujujiexi\modules\v1\models\Schedule.php,其内容,如图26
30、配置URL规则,修改urlManager组件的配置,如图27
31、配置模块规则,如图28
1 2 3 4 5 6 | 'modules' => [ 'v1' => [ 'basePath' => '@app/modules/v1' , 'class' => 'shujujiexi\modules\v1\Module' ], ], |
31、在Postman中GET:shujujiexi.kaiqiu_shujujiexi_api.dev/schedules,404响应,符合预期,如图29
32、在Postman中GET:shujujiexi.kaiqiu_shujujiexi_api.dev/v1/schedules,正确响应,如图30
33、响应数据的结构调整,默认为code、message、data字段
34、复制\vendor\yiisoft\yii2\rest\Serializer.php为\shujujiexi\rests\Serializer.php,其内容,继承至\yii\rest\Serializer,且只保留serializeDataProvider(),如图31
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 shujujiexi\rests; use Yii; /** * 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 Xue <qiang.xue@gmail.com> * @since 2.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 ; } else { $result = [ $this ->collectionEnvelope => $models , ]; if ( $pagination !== false) { return [ 'code' => '00000' , 'message' => 'success' , 'data' => array_merge ( $result , $this ->serializePagination( $pagination ))]; // return array_merge($result, $this->serializePagination($pagination)); } else { return [ 'code' => '00000' , 'message' => 'success' , 'data' => $result ]; // return $result; } } } } |
35、编辑控制器\shujujiexi\controllers\ScheduleController.php,如图32
36、在Postman中GET:shujujiexi.kaiqiu_shujujiexi_api.dev/v1/schedules,正确响应,如图33
37、如何自由定义此请求的响应的实现流程,分析\vendor\yiisoft\yii2\rest\ActiveController.php可发现,Index操作默认实现类为yii\rest\IndexAction,如图34
38、复制\vendor\yiisoft\yii2\rest\IndexAction.php至\shujujiexi\rests\schedule\IndexAction.php,如图35
39、编辑控制器\shujujiexi\controllers\ScheduleController.php,如图36
1 2 3 4 5 6 7 8 | public function actions() { $actions = parent::actions(); $actions [ 'index' ][ 'class' ] = 'shujujiexi\rests\schedule\IndexAction' ; return $actions ; } |
40、编辑\shujujiexi\rests\schedule\IndexAction.php,如图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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | <?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace shujujiexi\rests\schedule; use Yii; use yii\rest; use yii\data\ActiveDataProvider; /** * @author Qiang Xue <qiang.xue@gmail.com> * @since 2.0 */ class IndexAction extends rest\IndexAction { /** * @var callable a PHP callable that will be called to prepare a data provider that * should return a collection of the models. If not set, [[prepareDataProvider()]] will be used instead. * The signature of the callable should be: * * ```php * function ($action) { * // $action is the action object currently running * } * ``` * * The callable should return an instance of [[ActiveDataProvider]]. */ /** * Prepares the data provider that should return the requested collection of the models. * @return ActiveDataProvider */ protected function prepareDataProvider() { if ( $this ->prepareDataProvider !== null) { return call_user_func( $this ->prepareDataProvider, $this ); } /* @var $modelClass \yii\db\BaseActiveRecord */ $modelClass = $this ->modelClass; return new ActiveDataProvider([ 'query' => $modelClass ::find()->where([ 'status' => 1]), ]); } } |
41、在Postman中GET:shujujiexi.kaiqiu_shujujiexi_api.dev/v1/schedules,正确响应,且仅返回status为1的数据,如图38
备注:
1、基于 Gii 生成的模型文件存放于common目录;
2、v1,控制器与模型中的方法建议在\shujujiexi\controllers、\shujujiexi\models中实现;
3、v2,如果需要有不同的功能实现,控制器与模型中的方法建议在\shujujiexi\modules\v1\controllers、\shujujiexi\modules\v1\models中覆盖实现;
4、shujujiexi\rests,其目录结构类似于shujujiexi\views,每一个控制器有其对应的目录;
5、在每一个主要版本 (在相应的模块),使用 Accept HTTP 请求头 确定小版本号编写条件代码来响应相应的次要版本;
// 通过参数
Accept: application/json; version=1.0.0
1 条回复
[…] […]