l5如何通过路由走api版本回退查找设置

具体需求

当前遇到的问题是使用laravel写接口,但是接口是有版本号的,我们把版本号放在url中,比如:

  1. http://yejianfeng.com/api/user/info/?uid=1
  2. http://yejianfeng.com/api1.1/user/info/?uid=1
  3. http://yejianfeng.com/api1.2/user/info/?uid=1

但是实际上api1.1的user/info和api的user/info的action是一样的,但是api1.2的user/info是不一样的

本来路由应该这么写:

  1. <?php
  2. Route::group(array('prefix' => 'api'), function() {
  3. Route::get('/user/info', ['uses' => 'UserController@userinfo']);
  4. });
  5. Route::group(array('prefix' => 'api1.1'), function() {
  6. Route::get('/user/info', ['uses' => 'UserController@userinfo']);
  7. });
  8. Route::group(array('prefix' => 'api1.2'), function() {
  9. Route::get('/user/info', ['uses' => 'UserController@userinfo1_2']);
  10. });

这个感觉还是丑了点,我不希望路由会这么复杂,我希望的是进行版本衰退寻找,api1.1中的user/info那个不需要写,它能自动去寻找api1.1中有没有这个路由,没有的话,去寻找比它版本低的路由。

解决方法

这里当然要使用到middleware,希望路由是:

  1. <?php
  2. Route::group(array('prefix' => 'api'), function() {
  3. Route::get('/user/info', ['uses' => 'UserController@userinfo']);
  4. });
  5. Route::group(array('prefix' => 'api1.1', 'middleware' => 'downgrade'), function() {
  6. });
  7. Route::group(array('prefix' => 'api1.2', 'middleware' => 'downgrade'), function() {
  8. Route::get('/user/info', ['uses' => 'UserController@userinfo1_2']);
  9. });

但是非常可惜,这样写的话

  1. http://yejianfeng.com/api1.1/user/info/?uid=1

是进不了middleware的。

我们需要的是有个“匹配所有”的路由能将路由定位定到prefix 1.1的这个里面

所以改成这样:

  1. <?php
  2. Route::group(array('prefix' => 'api'), function() {
  3. Route::get('/user/info', ['uses' => 'UserController@userinfo']);
  4. });
  5. Route::group(array('prefix' => 'api1.1', 'middleware' => 'downgrade'), function() {
  6. Route::any('/{c}/{a}', function(){});
  7. });
  8. Route::group(array('prefix' => 'api1.2', 'middleware' => 'downgrade'), function() {
  9. Route::get('/user/info', ['uses' => 'UserController@userinfo1_2']);
  10. Route::any('/{c}/{a}', function(){});
  11. });

这里就能将所有的/{version}/{controller}/{action}这样的请求经过downgrade中间件了。

但是中间件怎么写呢?

downgrade中间件的编写

  1. <?php namespace App\Http\Middleware;
  2. use Closure;
  3. use Illuminate\Contracts\Routing\Middleware;
  4. class DownGradeMiddleware implements Middleware {
  5. public function handle($request, Closure $next)
  6. {
  7. $routeAction = $request->route()->getAction();
  8. $routes = \Route::getRoutes()->getRoutes();
  9. $requestUri = $_SERVER['REQUEST_URI'];
  10. $querys = explode('?', $requestUri);
  11. $queryPath = trim($querys[0], '/');
  12. $querySecs = explode('/', $queryPath);
  13. // 没有对应的,进行api版本回找
  14. $versions = ['api', 'api1.1', 'api1.2'];
  15. $apiversion = $querySecs[0];
  16. $key = array_search($apiversion, $versions);
  17. while (1) {
  18. if ($key < 0) {
  19. break;
  20. }
  21. $querySecs[0] = $versions[$key];
  22. $queryPath = trim(implode('/', $querySecs), '/');
  23. foreach ($routes as $route) {
  24. if ($route->getUri() == $queryPath) {
  25. $action = $route->getAction();
  26. $routeAction['uses'] = $action['uses'];
  27. $request->route()->setAction($routeAction);
  28. return $next($request);
  29. }
  30. }
  31. $key--;
  32. }
  33. $response = $next($request);
  34. return $response;
  35. }
  36. }

这里最重要的点就是将$routeAction的uses字段修改之后,调用

  1. $request->route()->setAction($routeAction);

就可以修改路由对应的action了

其他的就是业务逻辑的问题了。

至于如何挂载middleware,可以参考laravel文档:路由进行挂载

总结

laravel4把匹配全路由的函数去掉了,但是其实使用中间件+any("{a}/{b}/{c}") 的方法也可以近似实现一个这样的功能的。

so,总是有路通向罗马的。

l5如何通过路由走api版本回退查找设置的更多相关文章

  1. Git的纯命令操作,Install,Clone , Commit,Push,Pull,版本回退,撤销更新,分支的创建/切换/更新/提交/合并,代码冲突

    Git的纯命令操作,Install,Clone , Commit,Push,Pull,版本回退,撤销更新,分支的创建/切换/更新/提交/合并,代码冲突 这篇是接着上篇分布式版本库--Windows下G ...

  2. git 版本回退

    由于操作失误,需要将代码进行版本回退,首先在本地仓库执行了“git reset --hard HEAD^”命令,这样只会回退本地仓库的代码,但是我的代码之前已经push到了远程库中,查看远程仓库,发现 ...

  3. git误删文件找回方法/git版本回退方法

    使用git命令 git rm css/\*.css 我删掉了css文件夹下所有以.css结尾的文件,那么要怎样才能把文件找回来呢,下面说说方法,删掉其他的文件也是一样的方式找回. 第一步:使用git ...

  4. git版本回退, github版本回退

    上周提交了更改,过了周末回来说要撤销上个story.于是,需要找到上周提交的版本,rollback回来. git版本管理命令,自从习惯使用管理工具之后就很少接触了,当突然寻找其他指令的时候就成浆糊了, ...

  5. 【Git学习笔记】初始化Git仓库和版本回退

    学习地址 http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 什么是版本库呢?版本库又 ...

  6. git中的版本回退

    git版本回退有两种情况,一种是从本地版本库中(head区)回退到某个版本,可以用命令 git reset --hard head^ 或git reset --hard head~x ,head指的是 ...

  7. Git秘籍:在 Git 中进行版本回退

    导读 在这篇文章中,你将学到如何查看项目中的历史版本,如何进行版本回退,以及如何创建 Git 分支以便你可以大胆尝试而不会出现问题.快来试试吧. 在你的 Git 项目的历史中,你的位置就像是摇滚专辑中 ...

  8. SVN版本回退

    [SVN版本回退] 在Windows里,先打开Log面板,根据想要回退的内容,然后选择revert to this revision或者revert changes from this revisio ...

  9. git分支与版本管理、版本回退、冲突解决记录

    一.基础使用 1.初始化本地仓库 git init 2.关联远程仓库 git remote add origin git@github.com:用户名/仓库名.git 3.添加远程仓库文件到本地 gi ...

随机推荐

  1. 调试SQLSERVER (一)生成dump文件的方法

    调试SQLSERVER (一)生成dump文件的方法 调试SQLSERVER (二)使用Windbg调试SQLSERVER的环境设置调试SQLSERVER (三)使用Windbg调试SQLSERVER ...

  2. Ubuntu Server 15.04的安装

    U盘启动工具的制作就跟Windows系统以及Linux各版本的desktop版不同,用的工具也是我第一次见到的“Win32_Disk_Imager”(点击下载) 安装过程请参考:http://www. ...

  3. CentOs笔记

    系统 CentOs7,最小安装,使用 Ext4,/ ,/boot,/swap 使用标准分区,另一个分区做为数据分区,使用 LVM. 更新: http://mirrors.163.com/.help/c ...

  4. TW2015技术雷达中文版发布

    今天thoughtworks 2015新版技术雷达pdf发布了,你可以从这里下载http://engage.thoughtworks.com/HQ0000Q0QOf5pE70nbD00GP,在这里你可 ...

  5. 使用ACE_Task管理线程

    为什么要使用ACE_Task来管理线程 从C#转到C++后,感觉到C++比C#最难的地方,就是在系统编程时,C#中有对应的类库,我接触到一个类后,就可以通过这个类,知道很多相关的功能.而在C++中,必 ...

  6. java提高篇(八)----详解内部类

    可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面 ...

  7. Kinect for Windows SDK 1.8的改进及新特性

    今年3月, 微软推出了Kinect for Windows SDK 1.7 更新,包括了手势识别 Kinect Interactions 和实时 3D 建模 Kinect Fusion 两项新技术. ...

  8. JavaScript思维导图—数组

    JavaScript思维导图-来自@王子墨http://julying.com/blog/the-features-of-javascript-language-summary-maps/

  9. 自制Unity小游戏TankHero-2D(2)制作敌方坦克

    自制Unity小游戏TankHero-2D(2)制作敌方坦克 我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的. ...

  10. 我心中的核心组件(可插拔的AOP)~第十三回 实现AOP的拦截组件Unity.Interception

    回到目录 说在前 本节主要说一下Unity家族里的拦截组件,对于方法拦截有很多组件提供,基本上每个Ioc组件都有对它的实现,如autofac,它主要用在orchard项目里,而castle也有以拦截的 ...