为每个API版本使用单独的目录

时间:2017-12-26 21:35:59

标签: php laravel api api-versioning

我打算用Laravel框架创建一个API。如果我继续开发API,可能会有多个版本的API,例如:v1v2v3等。

而不是只有一个Laravel框架副本,并通过为每个版本创建不同的目录对其中的API进行版本控制,我正在考虑为每个版本的API创建一个完全独立的Laravel框架副本。

例如,假设这是API的URL:website.com/api,我正在考虑在v1目录中创建一个名为api的目录,并提供完整的副本Laravel在里面。稍后,当我需要创建新版本的API时,我将在v2旁边创建另一个名为v1的新目录,并在其中放入一个新的完整且独立的Laravel副本,依此类推。< / p>

这样,当我想访问API的第1版时,我将访问此网址:website.com/api/v1,当我想访问版本2时,我将访问website.com/api/v2

我的问题:这是个坏主意吗?这种方法的缺点是什么?

修改

为什么我会想到这种方法?

因为我想到了以下几点:

  • 如果有一天我想要使用除Laravel之外的PHP框架创建新版本API,该怎么办。
  • 如果有一天我想用PHP以外的编程语言创建新版API,该怎么办?
  • 如果有一天我想要升级到更新版本的Laravel并且该版本对最初创建API的版本进行了重大更改,那该怎么办呢?

6 个答案:

答案 0 :(得分:7)

我认为这是一个坏主意 - 重复代码堆,重复维护,绝对没有优势。

构建当前用例

首先:

  

您需要构建技术以满足当前的使用案例(非常   不久的将来)

许多CTO /技术架构师通常有时会对未来进行过多考虑。如果我的音量增加1000倍怎么办?我应该使用大数据堆栈吗?不,当然不会,除非你预计它将在未来3个月内发生!

您的方法的缺点

  1. 代码重复:您最终会复制如此多的代码 - 您的Eloquent模型,业务逻辑,身份验证,中间件等。
  2. 维护&amp;其他开销:根据您的技术堆栈,维护也会重复。对于例如想象一下在多个应用程序上运行Artisan命令以进行简单的配置缓存刷新。更不用说依赖性,硬件资源等的单独升级。
  3. <强>优点

    您的方法没有明显的优势。让我们看一下驱使您走向这个架构的具体问题:

    1. 如果有一天我想用Laravel以外的PHP框架创建新版本的API怎么办?
    2. 我们假设您目前有3个版本,并且您希望在不同的框架上创建版本#4。好吧,你仍然可以在单个Laravel应用程序上拥有前3个版本,在不同的应用程序/代码库上拥有第4个版本。如果您已有3个现有版本,则没有理由将它们作为单独的Laravel应用程序

      1. 如果有一天我想用PHP以外的编程语言创建新版API,该怎么办?
      2. 嗯,这同样适用于此。如果出现这种情况,您可以随时为不同语言的未来版本提供不同的应用程序

        1. 如果有一天我想要升级到更新版本的Laravel并且该版本对最初创建API的版本进行了重大更改,那该怎么办呢?
        2. 次要版本在Laravel中向后兼容。因此,如果您从Laravel 5.1升级到5.5,那么应该没有重大变化。对于主要的应用程序,您可以选择不同的应用程序(如果需要),但实际上,即使是主要的版本升级也可能不是一个挑战。当然,您可以使用Laravel Shift等工具轻松升级

答案 1 :(得分:6)

我的建议:

使用子域名

让您的API可以在以下网址获取:mobile.laravel.appapi.laravel.app

这使您可以灵活地为api使用不同的服务器(因此使用不同的框架),或者继续为您的应用程序使用相同的laravel应用程序。您可以在laravel中使用sub-domain routing来使用同一个应用处理多个域。

您的版本控制策略

通常将api的版本号保存为{major}。{minor}(内联语义版本控制)。未成年人向后兼容。

e.g。

api.laravel.com/v1.2/...

v1.api.laravel.com/...

(特别是如果它指向不同的IP地址)。

同样,您可以根据您正在进行的更改,选择指向其他服务器或文件夹或不同的控制器。

将Laravel用于版本化API

我工作的大部分项目都在Laravel上,这就是我们在Laravel中处理版本控制的方式。

Apis是在以下子域名中收到的:api.laravel.app

API已版本化,可在api.laravel.app/v1/...api.laravel.app/v2/...

处获取

处理这些API的控制器分组在文件夹

App
|-Http
  |-Controllers
     |-API
        |-v1
           - controllers for v1
        |-v2
           - controllers for v2

如果将来某个日期,您想要更改服务器,平台或使用不同版本的laravel等 - 您可以通过不同的子域进行处理。

我仍然建议你制定一个&#34;路线图&#34;和com模板功能以及每次3-6个月的版本号。

答案 2 :(得分:5)

  

我想创建一个完全独立的Laravel副本   每个API版本的框架。

为什么要复制整个框架,没有必要这样做。这样做会有相同文件的许多版本,最终会出现重复的代码。如果您发现所有常见方法中的错误,该怎么办? 版本,您必须在所有版本中进行更改。

  
      
  • 如果有一天我想要使用除Laravel之外的PHP框架创建新版本API,该怎么办。
  •   
  • 如果有一天我想用PHP以外的编程语言创建新版API,该怎么办?
  •   
  • 如果有一天我想要升级到更新版本的Laravel并且该版本对API的版本有重大改变,该怎么办?   最初是用。创建的。
  •   

您的所有3点与组织API的方式无关,只要您更改语言或框架,就必须重写它,除非它只是版本更改。

基于预见语言变化或框架而制定API结构是没有意义的。 Ebay,Paypal,Facebook,Google等都改变了他们的选择语言并在某个时间点改写了他们的代码库。他们没有预见到这种变化,并根据这一点制定了他们的系统。

所以我可以看到很多缺点。

方法1:

相反,我更喜欢最佳做法是版本控制您的API在不同的分支或标记它们,就像laravel本身所做的那样。 (见下图)

enter image description here

优点:

  • 轻松切换API&#39;
  • 使用IDE很舒服,因为不会有相同的名称文件进行搜索和编辑,因此您不会错误地编辑不同的版本。
  • 任何时候您都可以更新任何版本。
  • 查看更改历史记录
  • 使用此方法在不同的文件夹副本上进行开发时,您将体验到更多。

方法2:

我可以看到并且我已经完成的另一个选项是将API与版本特定的前缀分组。如果您希望一次运行所有版本并使用单一副本。但这不太值得推荐。

根据版本更改方法名称或控制器名称,或将它们放在特定于版本的名称空间中

请参阅下面的代码段:

/* Version v1  */
Route::prefix('v1')->group(function () {
    Route::get('users','UsersController@index');
    Route::get('foobars','FooController@bar');
});

/* Version v2  */
Route::prefix('v2')->group(function () {
    Route::get('users','UsersController@index'); 
    Route::get('foobars','FooController@bar');
});

优点:

  • 在一个项目中一次运行所有版本
  • 组织良好,路由,
  • 控制器,模型的命名空间智能版本。 (您可以保留常用控制器,并使用版本号作为前缀方法名称,以减少复制粘贴工作。)
  • 无分支切换

注意:两者都是特定于情境的方法,如果新版本中的变化少于5或10,我会选择方法2.但这是个别特定的选择。

答案 3 :(得分:0)

是的,你是对的。这是一个非常糟糕的主意。而挑战在于,即使只考虑单一优势,也没有。但

我建议您坚持使用一个安装,并且可以使用Dingo API。一个包,可以为您提供开箱即用的一套工具和标准API实践。根据需要包括v1v2等版本控制。

这将提高您的代码可重用性以及许多其他有助于您构建标准API的东西。

祝你好运。

答案 4 :(得分:0)

这不是这个问题的答案,因为你说你“计划”使用laravel,我想推荐另一个支持REST API版本的平台。

https://apigility.org/

Apigility,使用zendframework作为基础,如果您对使用其他框架感兴趣,我推荐它。

答案 5 :(得分:0)

如果我理解正确,你就是&#34;混合&#34;您的开发和部署架构。

根据您的网址路径(如您所建议的)甚至是子网域,我在您的生产环境中看到您的API的多个版本没有任何问题。

您的控件版本(git,svn等)应该考虑您可能拥有的每个API版本。如果您想开发新版本:创建一个新分支,开发并测试它,然后创建一个标记。

然后,当您部署应用程序本身时,您就关心如何通过特定路径或域访问它。