ii2 官方給出的方案是基於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',
],
],
],