12

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

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

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

这样,当我想访问 API 的版本 1 时,我将访问这个 URL:website.com/api/v1而当我想访问版本 2 时,我将访问website.com/api/v2.

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


编辑:

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

因为我想到了以下几点:

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

6 回答 6

9

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

为当前用例构建

首先:

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

如此多的 CTO/技术架构师有时会因为过多地考虑未来而弄错了。如果我的音量增加 1000 倍怎么办?我应该使用大数据堆栈吗?不,当然不会,除非您预计它会在接下来的 3 个月内发生!

你的方法的缺点

  1. 代码重复:你最终会重复很多代码——你的 Eloquent 模型、业务逻辑、身份验证、中间件等。
  2. 维护和其他开销:根据您的技术堆栈,维护也会重复。例如,想象在多个应用程序上运行 Artisan 命令以进行简单的配置缓存刷新。更不用说对依赖项、硬件资源等的单独升级了。

优点

您的方法没有明显的优势。让我们看一下促使您转向此架构的具体问题:

  1. 如果有一天我想用 Laravel 以外的 PHP 框架创建一个新版本的 API 怎么办?

假设您当前有 3 个版本,并且您想在不同的框架上创建版本 #4。好吧,你仍然可以在单个 Laravel 应用程序上拥有前 3 个版本,在不同的应用程序/代码库上拥有第 4 个版本。如果您已经有 3 个现有版本,则没有理由将它们作为单独的 Laravel 应用程序

  1. 如果有一天我想用 PHP 以外的编程语言创建 API 的新版本,该怎么办?

好吧,这同样适用于这里。如果出现这种情况,您始终可以为不同语言的未来版本提供不同的应用程序

  1. 如果有一天我想升级到更新版本的 Laravel,并且该版本对最初创建 API 的版本有重大更改,该怎么办。

次要版本在 Laravel 中向后兼容。所以,如果你从 Laravel 5.1 升级到 5.5,应该没有重大变化。对于主要版本,您可以选择不同的应用程序(如果需要),但实际上,即使是主要版本升级也可能不是挑战。当然,你可以使用Laravel Shift等工具让你轻松升级

于 2017-12-29T14:25:04.627 回答
6

我的建议:

使用子域

让您的 api 在以下网址可用:mobile.laravel.appapi.laravel.app.

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

您的版本控制策略

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

例如

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

或者

v1.api.laravel.com/...

(尤其是如果它指向不同的 IP 地址)。

同样,您可以根据所做的更改选择指向不同的服务器或文件夹或不同的控制器。

使用 Laravel 进行版本化 API

我从事的大多数项目都在 Laravel 上,这就是我们在 Laravel 中处理版本控制的方式。

API 在子域中收到,例如: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 等 - 您可以通过不同的子域进行处理。

我仍然建议一次在接下来的 3-6 个月内制定“路线图”和 com 模板功能和版本号。

于 2017-12-30T08:21:58.470 回答
5

我正在考虑为每个版本的 API 创建一个完全独立的 Laravel 框架副本。

为什么要复制整个框架,这样做没有意义。这样一来,您将拥有同一文件的多个版本,并且最终会出现重复的代码。如果你在所有版本中发现一个通用方法的错误,你必须在所有版本中更改它。

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

您的所有 3 点都与您如何组织 API 无关,一旦您更改语言或框架,您将不得不重写它,除非它只是版本更改。

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

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

方法一:

相反,我更喜欢最佳实践是对不同分支中的 API 进行版本控制,或者像 laravel 本身所做的那样标记它们。(见下图)

在此处输入图像描述

优点 :

  • 在 API 之间轻松切换
  • IDE舒适,不会有同名文件搜索和编辑,所以你不会误编辑不同的版本。
  • 任何时候都可以更新任何版本。
  • 查看更改历史
  • 在使用这种方法在不同的文件夹副本上进行开发时,您将体验到更多。

方法二:

我可以看到并且已经完成的另一个选项是将您的 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。但是这是个人特定的选择。

于 2018-01-02T14:00:57.533 回答
0

如果我理解正确,那么您正在“混合”您的开发和部署架构。

我在您的生产环境中没有看到任何问题,该环境具有基于 url 路径(如您所建议的)甚至子域的 API 的多个版本。

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

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

于 2018-01-02T11:19:49.683 回答
0

是的,你是对的。这是一个非常糟糕的主意。挑战甚至是想出一个单一的优势,但没有。

我会建议你坚持安装,你可以使用Dingo API。一个可以为您提供开箱即用的工具和标准 API 实践的包。包括版本控制v1v2如你所愿。

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

祝你好运。

于 2017-12-26T23:10:29.157 回答
0

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

https://apigility.org/

Apigility,使用zendframework作为基础,如果你有兴趣使用另一个框架,我推荐它。

于 2017-12-29T12:24:15.290 回答