路由版本控制的实现。

Laravel 版本:5.6.4
PHP 版本:7.3

背景介绍#

因为现在的项目确实遇到了 v1 慢慢迭代,到 v5 的情况了, 最开始是所有模块接口路由都放在了 api.php 一个文件,三千多行的路由配置, 每次新增,查找,修改 都非常的不方便,后来是通过 RouteServiceProvider.php 根据不同功能大模块,自定义了 几个新的路由文件, 可是随着版本的升级,又出现了 我发帖的这个问题,因为功能从 v1 ~ v5 其实就一个版本号改变了,其他的路径,方法名都没变,然而每次迭代一个新版本,又得复制一遍代码,只是改了一个版本号,这让我感觉非常的臃肿,和傻瓜。而且日积月累起来,依旧会导致一个功能类的路由文件非常大。

问题描述#

最近在写 Api 接口,为了不因为功能改动而影响之前的业务,这边想做一个版本控制,最开始在 api.php 路由文件路由分组的方式写死 版本号,可是随着项目迭代,会出现 v2,v3,v4 这样的话 就得定义很多的重复分组(只是版本号不同)。感觉这种方式一点都不优雅和简洁。
url: xxx.com/api/v1/users/list

Route::group(['prefix' => 'v1/users']function () { 
  //获取用户列表
  Route::get('/', 'v1\UserController@getUserList');
 }); 

 Route::group(['prefix' => 'v2/users']function () { 
  //获取用户列表
  Route::get('/', 'v2\UserController@getUserList');
 }); 

于是我这边就通过参数接收的方式,通过 url 传递过来的版本号,动态的处理版本控制,虽然看上去是解决了,无需重复写多个路由版本分组的方式,但是我还是觉得这种方式写出来的代码非常的臃肿。
url: xxx.com/api/v1/users/list

    //用户列表
    Route::group(['prefix' => '{version}/users'], function (){
        Route::get('/list', function ($version) {
            $class = 'App\Http\Controllers\\' . $version . '\\UsersController';
            if (class_exists($class)) {
                return app()->call([app()->make($class), 'getUserList']);
            }
            return abort(404);
        });
    });

不知道大家有没有更优雅的处理方式?#

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

file file

动态匹配版本前缀及命名空间。web.php 里面只需要基于 RouteServiceProvider。

3年前 评论
aliongkk 1年前
讨论数量: 19

file file

动态匹配版本前缀及命名空间。web.php 里面只需要基于 RouteServiceProvider。

3年前 评论
aliongkk 1年前
pndx

好像是可以在 middleware 设置前缀,然后在单独文件夹的,之前忘记哪里看到过的

3年前 评论

一般是这样的

Route::group(['prefix' => 'v1', 'namespace' => 'V1'], function () {
  //
});
Route::group(['prefix' => 'v2', 'namespace' => 'V2'], function () {
  //
});

dingo 不是路由前缀区分的,而是 header 头携带版本号,但路由写法大同小异

$api = app('Dingo\Api\Routing\Router');

$api->version('v1', function ($api) {
    $api->get('demo', 'App\Http\Controllers\Api\V1\DemoController@index');
});

$api->version('v2', function ($api) {
    $api->get('demo', 'App\Http\Controllers\Api\V2\DemoController@index');
});
3年前 评论
Epona

v1 v2 就可以了, 代码的可维护性和 阅读性更重要。 有时候写一些骚代码, 过段时间回来自己看这写的是啥, 我怎么看不懂。

或者像楼上说的, 将 v1, v2 放到各自的文件中。

3年前 评论

v1 v2 这样是没问题的,声明重复路由也没关系,在项目更新迭代中,冗余是难免的,重要的是从维护性和可读性。

3年前 评论

因为现在的项目确实遇到了 v1 慢慢迭代,到 v5 的情况了, 最开始是所有模块接口路由都放在了 api.php 一个文件,三千多行的路由配置, 每次新增,查找,修改 都非常的不方便,后来是通过 RouteServiceProvider.php 根据不同功能大模块,自定义了 几个新的路由文件, 可是随着版本的升级,又出现了 我发帖的这个问题,因为功能从 v1 ~ v5 其实就一个版本号改变了,其他的路径,方法名都没变,然而每次迭代一个新版本,又得复制一遍代码,只是改了一个版本号,这让我感觉非常的臃肿,和傻瓜。而且日积月累起来,依旧会导致一个功能类的路由文件非常大。

3年前 评论
php_yt 3年前
周小云 3年前

也许你需要的是这样,命名空间需要你根据自己实际调整

路由文件:


//v1前缀使用V1命名空间下的控制器
Route::group(['prefix' => 'v1','namespace' => 'Controllers\V1']function () { 
  //获取用户列表
  include 'user.php';
 }); 

//v2前缀使用V@命名空间下的控制器
 Route::group(['prefix' => 'v2','namespace' => 'Controllers\V2']function () { 
  //获取用户列表
  include 'user.php';
 }); 

user.php

Route::get('user', 'UserController@getUserList');

这样你只需要把路由一个个 include 到对应版本里就行

3年前 评论
黑将军

可以在 RouteServiceProvider 里设置前缀

3年前 评论
an_an (楼主) 3年前
黑将军 (作者) 3年前
uax

With Laravel you can version your API very easily.

This snippet will:

  • Prefix your URL with /api/v1
  • Use the routes from /routes/v1.php

file

3年前 评论

如果并发达到一定量级 class_exists 会占用大量磁盘 I/O,不建议将其用在所有请求的判断中。

3年前 评论

file file

动态匹配版本前缀及命名空间。web.php 里面只需要基于 RouteServiceProvider。

3年前 评论
aliongkk 1年前

你可以按版本按功能独立拆分出来

file

RouteServiceProvider 里只需要循环加载即可

file

3年前 评论
pardon110

版本控制一般有一定义的语义,比如 v1.2.3,就楼主给出的描述而言是本质上是次版本升级

v1..2.3
1  主版本,主版本不同代码前后不兼容
2  次版本   主版本一致,代码前后兼容
3  补丁
3年前 评论