api 接口版本控制找了一下资料总共有几种类型
- 不设定版本模式意味着每个API只提供一个版本,如果要修改本API, 所有的用户都必须使用最新的API,任何API的修改都会影响到所有的用户。
- API自带版本模式同一个名称的API可以建立多个版本,API调用方根据自己的需求选择使用对应的API版本。新版本与老版本共存,意味着老版本用户不会受新版本更新的影响。
- 兼容性版本模式每个API只有一个版本,API需要兼容以前老版本API的功能。所有版本用户都调用同一个API,通过内在代码保证兼容性。
具体一些内容可以看一下介绍https://juejin.im/post/5977f8ba5188255b9a6ad820
解决版本控制有5种类型
1.url增加版本编号
http://localhost/index.php/home/v1/index/test
2.url增加版本信息
http://localhost/index.php/home/index/test/v1
3.新增接口
http://localhost/index.php/home/index/newTest
4.客户端在做请求的时候在HTTP HEAD里面中添加API-VERSION字段,标识出请求的是哪个接口:
-H "API-VERSION: v1"
-H "API-VERSION: v2"
5.不同版本使用不同的域名,这样:
v1.api.xxx.com
v2.api.xxx.com
以下代码是基于TP3.2.3修改的:
用的是第一种url增加版本编号:http://localhost/index.php/home/v1/index/test
修改这个代码做法是:url可以全部统一修改为最新版本,如果最新版本不存在会自动查找低版本的接口
在网上查找的资料都是可以用那几种类型,没有具体事例,下面是我自己想法修改出来的代码。
修改的tp入口文件名 app.class.php
/**
* 执行应用程序
* @access public
* @return void
*/
static public function exec() {
if(!preg_match('/^[A-Za-z](\/|\w)*$/',CONTROLLER_NAME)){ // 安全检测
$module = false;
}elseif(C('ACTION_BIND_CLASS')){
// 操作绑定到类:模块\Controller\控制器\操作
$layer = C('DEFAULT_C_LAYER');
if(is_dir(MODULE_PATH.$layer.'/'.CONTROLLER_NAME)){
$namespace = MODULE_NAME.'\\'.$layer.'\\'.CONTROLLER_NAME.'\\';
}else{
// 空控制器
$namespace = MODULE_NAME.'\\'.$layer.'\\_empty\\';
}
$actionName = strtolower(ACTION_NAME);
if(class_exists($namespace.$actionName)){
$class = $namespace.$actionName;
}elseif(class_exists($namespace.'_empty')){
// 空操作
$class = $namespace.'_empty';
}else{
E(L('_ERROR_ACTION_').':'.ACTION_NAME);
}
$module = new $class;
// 操作绑定到类后 固定执行run入口
$action = 'run';
}else{
//创建控制器实例
/****以下是修改的代码******/
$p = CONTROLLER_NAME;
$c = explode('/', $p);
$mod = substr($c[0], 0,1);
if ($mod!='V') {
$action = $c[1];
$p = 'V1/'.substr($p, 0,stripos($p,'/'));
}
if (!controller($p)) {
$p = explode('/', $p);
$n = substr($p[0], 1);
$b = 'V'.$n;
while (!controller($b.'/'.$p[1])) {
$n = --$n;
$b = 'V'. $n;
if ($n==0) {
break;
}
if (controller($b.'/'.$p[1])) {
$module = controller($b.'/'.$p[1]);
break;
}
}
}else{
// $module = controller(CONTROLLER_NAME,CONTROLLER_PATH);
$module = controller($p);
$p = explode('/', $p);
$n = substr($p[0], 1);
}
}
if(!$module) {
if('4e5e5d7364f443e28fbf0d3ae744a59a' == CONTROLLER_NAME) {
header("Content-type:image/png");
exit(base64_decode(App::logo()));
}
// 是否定义Empty控制器
$module = A('Empty');
if(!$module){
E(L('_CONTROLLER_NOT_EXIST_').':'.CONTROLLER_NAME);
}
}
// 获取当前操作名 支持动态路由
if(!isset($action)){
$action = ACTION_NAME.C('ACTION_SUFFIX');
}
try{
self::invokeAction($module,$action);
} catch (\ReflectionException $e) {
// 方法调用发生异常后 引导到__call方法处理
self::isAction($n,$p,$action);
$method = new \ReflectionMethod($module,'__call');
$method->invokeArgs($module,array($action,''));
}
return ;
}
//增加判断该方法不存在时 查找下一个控制
public static function isAction($n,$p,$action){
if ($n==1) {
$module = controller($b.'/'.$p[1]);
self::isController($module);
try{
self::invokeAction($module,$action);
} catch (\ReflectionException $e) {
// 方法调用发生异常后 引导到__call方法处理
$method = new \ReflectionMethod($module,'__call');
$method->invokeArgs($module,array($action,''));
}
}
$b = 'V'.--$n;
if (controller($b.'/'.$p[1])) {
$module = controller($b.'/'.$p[1]);
try{
self::invokeAction($module,$action);
} catch (\ReflectionException $e) {
// 方法调用发生异常后 引导到__call方法处理
self::isAction($n,$p,$action);
$method = new \ReflectionMethod($module,'__call');
$method->invokeArgs($module,array($action,''));
}
}
self::isAction($n,$p,$action);
}