棂壹 2018-01-08 17:39:22 7200次浏览 2条评论 2 0 0

Yii2 官方给出的方案是基于url的版本控制,但是我们的versoin放在header里面,需要通过header来进行版本控制,实现如下:
首先在基类中实现actions,actions是针对controller的action扩展,看源码可以知道,在createAction中会先检查actionMap,而actionMap=actions(),也就是说actions里面的配置优先于controller的inline actions,这样我们就可以更改action了

public function actions()
{
    $parent = parent::actions();
    //通过Version类去统一控制,传递$this,使得调用对应action时能找到对应的类
    $actions = (new Version())->convertActionMap($this);
    return array_merge($parent, $actions);
}

Version类的实现

class Version
{
    //改成你们hearder中的version标识字段
    public $versionParam = "Appver";
    public $actionMap = null;

    public function getVersion()
    {
        return Yii::$app->getRequest()->getHeaders()->get($this->versionParam);
    }

    public function getActionMap()
    {
        if ($this->actionMap === null) {
            $version = $this->getVersion();
            $controller = Yii::$app->controller->id;
            //version的配置我是放到了params里面,如果实现不一样,可以自己修改成方法调用
            $version_map = Yii::$app->params['version_map'] ?? [];
            $version_map = $version_map[$version] ?? [];
            $this->actionMap = $version_map[$controller] ?? [];
        }
        return $this->actionMap;
    }

    // 这个方法是给actions()调用的方法,需要传递具体的类$class,不然在执行action的时候会找不到对应的类报错
    public function convertActionMap($class) {
        $action_map = $this->getActionMap();
        // 组装映射格式
        foreach ($action_map as $key => $map) {
            if (strpos($map, 'action') === false) {
                $map = 'action' . trim($map);
            }
            $action_map[$key] = [$class, $map];
        }

        return $action_map;
    }
}

params的配置

'version_map' => [
        // version
        '1.1.1' => [
            // 对应的controllerId
            'login' => [
                // 端上访问的action => 根据版本控制实际访问的action
                'index' => 'index1',
            ],
        ],
    ],

这样当版本号是1.1.1时访问 your_host/login/index 实际调用的是your_host/login/index1
非1.1.1版本 还是调用your_host/login/index

您需要登录后才可以评论。登录 | 立即注册