最近在研究 yii2 如何搭建 restful api,将心得写下,欢迎一起讨论
使用yii2.0.13 advanced 版,将 frontend 整个作为 api 接口项目,除了接口的路由规则可以认证通过外,其他的路由规则都返回请求错误的格式
1、数据库结构
CREATE TABLE `goods` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `price` int(11) unsigned NOT NULL, `status` tinyint(1) unsigned NOT NULL, `create_time` int(11) unsigned NOT NULL, `modify_time` int(11) unsigned NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
2、使用 gii 创建 goods model
3、创建 api modules
在 frontend 下新建文件夹 modules
使用 gii 在 modules 文件中创建 v1 module(防止以后接口更新替换时向前兼容,接口增加 v1 v2 等版本控制)
4、将 v1 moduel 写到配置文件中
'modules' => [ 'v1' => [ 'class' => 'frontend\modules\v1\Module', ], ],
5、修改 frontend 下 main.php 中,user 的配置(以下说的配置文件,都是 frontend 下 main.php)
'user' => [ 'identityClass' => 'frontend\models\User', 'enableAutoLogin' => false, 'enableSession' => false, 'loginUrl' => null, ],
6、新建 frontend\models\User,继承 common\models\User
<?phpnamespace frontend\models;class User extends \common\models\User{ }
7、启用并修改配置文件中的 urlManager
调试 urlManager 的时候要小心,他会将生成好的路由写入缓存(默认是文件缓存),有些更改可能不会立马生效
'urlManager' => [ //用于表明 urlManager 是否启用 URL 美化功能 //默认不启用。但实际使用中,特别是产品环境,一般都会启用 'enablePrettyUrl' => true, //是否启用严格解析,如启用严格解析,要求当前请求应至少匹配1个路由规则,否则认为是无效路由。 //这个选项仅在 enablePrettyUrl 启用后才有效。 //如果开启,表示只有配置在 rules 里的规则才有效 //由于项目会将一些 url 进行优化,所以这里需要设置为 true 'enableStrictParsing' => true, //指定是否在URL在保留入口脚本 index.php 'showScriptName' => false, 'rules' => [ //当然,如果自带的路由无法满足需求,可以自己增加规则 'GET <module:(v)\d+>/<controller:\w+>/search' => '<module>/<controller>/search', [ 'class' => 'yii\rest\UrlRule', 'controller' => ['v1/goods'], // 由于 resetful 风格规定 URL 保持格式一致并且始终使用复数形式 // 所以如果你的 controller 是单数的名称比如 UserController // 设置 pluralize 为 true (默认为 true)的话,url 地址必须是 users 才可访问 // 如果 pluralize 设置为 false, url 地址必须是 user 也可访问 // 如果你的 controller 本身是复数名称 UsersController ,此参数没用,url 地址必须是 users 'pluralize' => false, ], ], ],
8、去掉配置文件中的 errorHandler 配置(整个 frontend 都是接口,不需要 html 的响应格式)
9、将内容协商配置到引导文件中(因为整个 frontend 都需要)
'bootstrap' => [ 'log', //全局内容协商 [ //ContentNegotiator 类可以分析request的header然后指派所需的响应格式给客户端,不需要我们人工指定 'class' => 'yii\filters\ContentNegotiator', 'formats' => [ 'application/json' => yii\web\Response::FORMAT_JSON, 'application/xml' => yii\web\Response::FORMAT_XML, //api 端目前只需要json 和 xml //还可以增加 yii\web\Response 类内置的响应格式,或者自己增加响应格式 ], ] ],
10、配置文件中,components 配置 response,返回格式
'response' => [ 'class' => 'yii\web\Response', //设置 api 返回格式,错误码不在 header 里实现,而是放到 body里 'as resBeforeSend' => [ 'class' => 'frontend\extensions\ResBeforeSendBehavior', 'defaultCode' => 500, 'defaultMsg' => 'error', ], //ps:components 中绑定事件,可以用两种方法 //'on eventName' => $eventHandler, //'as behaviorName' => $behaviorConfig, //参考 http://www.yiiframework.com/doc-2.0/guide-concept-configurations.html#configuration-format],
11、编写 frontend\extensions\ResBeforeSendBehavior 代码
<?phpnamespace frontend\extensions;use Yii;use yii\web\Response;use yii\base\Behavior;class ResBeforeSendBehavior extends Behavior{ public $defaultCode = 500; public $defaultMsg = 'error'; // 重载events() 使得在事件触发时,调用行为中的一些方法 public function events() { // 在 EVENT_BEFORE_SEND 事件触发时,调用成员函数 beforeSend return [ Response::EVENT_BEFORE_SEND => 'beforeSend', ]; } // 注意 beforeSend 是行为的成员函数,而不是绑定的类的成员函数。 // 还要注意,这个函数的签名,要满足事件 handler 的要求。 public function beforeSend($event) { try { $response = $event->sender; if($response->data === null){ $response->data = [ 'code' => $this->defaultCode, 'msg' => $this->defaultMsg, ]; } elseif(!$response->isSuccessful) { $exception = Yii::$app->getErrorHandler()->exception; if(is_object($exception) && !$exception instanceof yii\web\HttpException){ throw $exception; } else { $rData = $response->data; $response->data = [ 'code' => empty($rData['status']) ? $this->defaultCode : $rData['status'], 'msg' => empty($rData['message']) ? $this->defaultMsg : $rData['message'], ]; } } else { /** * $response->isSuccessful 表示是否会抛出异常 * 值为 true, 代表返回数据正常,没有抛出异常 */ $rData = $response->data; $response->data = [ 'code' => isset($rData['error_code']) ? $rData['error_code'] : 0, 'msg' => isset($rData['res_msg']) ? $rData['res_msg'] : $rData, ]; $response->statusCode = 200; } } catch (\Exception $e) { $response->data = [ 'code' => $this->defaultCode, 'msg' => $this->defaultMsg, ]; } return true; } }
12、创建 GoodsController.php
<?phpnamespace frontend\modules\v1\controllers; use yii\rest\ActiveController; class GoodsController extends ActiveController { public $modelClass = 'common\models\Goods'; public function actionSearch(){ return [ 'error_code' => 20, 'res_msg' => 'ok', ]; } }
13、应用入口同级增加.htaccess文件,隐藏index.php,以apache为例
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule .* index.php
14、测试
命令: curl -s -H Accept:application/xml http://local.rest.com/v1/goods/1 返回:<?xml version="1.0" encoding="UTF-8"?><response> <code>0</code> <msg> <id>1</id> <name>测试商品1</name> <price>600</price> <status>1</status> <create_time>1520490595</create_time> <modify_time>1520490595</modify_time> </msg></response>
命令: curl -s -H Accept:application/json http://local.rest.com/v1/goods/1返回: { "code":0, "msg":{ "id":"1", "name":"测试商品1", "price":"600", "status":1, "create_time":"1520490595", "modify_time":"1520490595" } }
命令: curl -s -H Accept:application/json http://local.rest.com/v1/goods11返回: {"code":404,"msg":"Page not found."}
命令: curl -s -H Accept:application/json http://local.rest.com/v1/goods/search返回: {"code":20,"msg":"ok"}
15、参考
http://www.yiichina.com/doc/guide/2.0/rest-quick-start
http://www.yiichina.com/doc/guide/2.0/runtime-handling-errors
http://www.yiiframework.com/doc-2.0/guide-concept-configurations.html#configuration-format
http://www.yii-china.com/post/detail/536.html
作者:smoke_zl
链接:https://www.jianshu.com/p/74d5dbb8af5e
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦