Yii2 基于header 实现接口版本控制 [ 2.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
棂壹
注册时间:2016-05-03
最后登录:2019-06-04
在线时长:6小时43分
最后登录:2019-06-04
在线时长:6小时43分
- 粉丝47
- 金钱90
- 威望80
- 积分950
共 2 条评论
请问这个actions是哪个基类中呢,yii2 restful api首先就会检查路由存不存在,不存在就直接报404,没办法进行拦截啊
有bug . 这种方式容易造成某些地方递归
比如 index => login 就会出错.
https://www.jianshu.com/p/87013edd78c2