Yii2 restful style building (1)

Recently, I am researching how to build a restful api in yii2, and write down my experience. Welcome to discuss
the use of yii2.0.13 advanced version, and use frontend as an api interface project. Except that the routing rules of the interface can be authenticated, other routing rules return request errors format

1. Database structure

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. Use gii to create a goods model

3. Create api modules

Create a new folder modules under the frontend and
use gii to create a v1 module in the modules file (to prevent forward compatibility when the interface is updated and replaced in the future, and version control such as v1 v2 will be added to the interface)

4. Write v1 moduel to the configuration file

'modules' => [
    'v1' => [
        'class' => 'frontend\modules\v1\Module',
    ],
],

5. Modify the configuration of user in main.php under frontend (the configuration files mentioned below are all main.php under frontend)

'user' => [
    'identityClass'     => 'frontend\models\User',
    'enableAutoLogin'   => false,
    'enableSession'     => false,
    'loginUrl'          => null,
],

6. Create a new frontend\models\User and inherit common\models\User

<?php

namespace frontend\models;

class User extends \common\models\User
{

}

7. Enable and modify the urlManager in the configuration file

Be careful when debugging urlManager, it will write the generated route into the cache (the default is the file cache), some changes may not take effect immediately

'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. Remove the errorHandler configuration in the configuration file (the entire frontend is an interface, no html response format is required)

9. Configure content negotiation into the bootstrap file (because the entire frontend needs it)

'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. In the configuration file, components configure response, return format

'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. Write frontend\extensions\ResBeforeSendBehavior code

<?php

namespace 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. Create GoodsController.php

<?php

namespace 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. Add .htaccess file at the same level of application entry, hide index.php, take apache as an example

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php

14. Test

命令:
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. Reference

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



Author: smoke_zl
Link: https://www.jianshu.com/p/74d5dbb8af5e
Source : Jianshu The
copyright belongs to the author. For commercial reprints, please contact the author for authorization, and for non-commercial reprints, please indicate the source.

 
 
G
M
T
 
 
Detect languageAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBengaliBosnianBulgarianCatalanCebuanoChichewaChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEsperantoEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekGujaratiHaitian CreoleHausaHebrewHindiHmongHungarianIcelandicIgboIndonesianIrishItalianJapaneseJavaneseKannadaKazakhKhmerKoreanLaoLatinLatvianLithuanianMacedonianMalagasyMalayMalayalamMalteseMaoriMarathiMongolianMyanmar (Burmese)NepaliNorwegianPersianPolishPortuguesePunjabiRomanianRussianSerbianSesothoSinhalaSlovakSlovenianSomaliSpanishSundaneseSwahiliSwedishTajikTamilTeluguThaiTurkishUkrainianUrduUzbekVietnameseWelshYiddishYorubaZulu
 
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBengaliBosnianBulgarianCatalanCebuanoChichewaChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEsperantoEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekGujaratiHaitian CreoleHausaHebrewHindiHmongHungarianIcelandicIgboIndonesianIrishItalianJapaneseJavaneseKannadaKazakhKhmerKoreanLaoLatinLatvianLithuanianMacedonianMalagasyMalayMalayalamMalteseMaoriMarathiMongolianMyanmar (Burmese)NepaliNorwegianPersianPolishPortuguesePunjabiRomanianRussianSerbianSesothoSinhalaSlovakSlovenianSomaliSpanishSundaneseSwahiliSwedishTajikTamilTeluguThaiTurkishUkrainianUrduUzbekVietnameseWelshYiddishYorubaZulu
 
 
 
 
 
 
 
 
 
Text-to-speech function is limited to 200 characters
 
 
Options : History : Feedback : Donate Close

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325256204&siteId=291194637