路由版本控制的实现。

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。

2年前 评论
aliongkk 9个月前
讨论数量: 19

file file

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

2年前 评论
aliongkk 9个月前

file file

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

2年前 评论
aliongkk 9个月前

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

路由文件:


//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到对应版本里就行

2年前 评论

一般是这样的

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');
});
2年前 评论
Epona

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

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

2年前 评论
pndx

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

2年前 评论

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

2年前 评论

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

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

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

file

RouteServiceProvider里只需要循环加载即可

file

2年前 评论
黑将军

可以在RouteServiceProvider里设置前缀

2年前 评论
an_an (楼主) 2年前
黑将军 (作者) 2年前
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

2年前 评论

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

2年前 评论
陈先生

file

2年前 评论
pardon110

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

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

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!