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