【问题标题】:Creating API versioning for my php application (Social App)为我的 php 应用程序(社交应用程序)创建 API 版本控制
【发布时间】:2019-05-28 21:08:01
【问题描述】:

我目前正在开发一个社交应用程序。

我想在我的 PHP 后端有一个版本控制系统,但我不知道从哪里开始:我在网上查了一堆文章,但我真的不明白我发现了什么。

假设我的应用程序是 v1.0。然后我创建了一个新版本 v2.0,当然我也更新了 PHP 文件。在此之后,如果有人没有从 v1.0 更新他们的应用程序,我希望他们联系myapp.com/v1.0/,这样应用程序就不会崩溃。

你会推荐什么?

我的一个典型的PHP文件是这样的,例如:

<?php

// Include files

include_once ('../../config.php');

include_once (ROOT_DIR . '/config/includes.php');

$_USERDATA = Validator::validateUser($_POST["userId"], $_POST["session"]);

// Valid session

$qry = $db->prepare('SELECT n.id, n.type, n.time, n.isRead, n.postId, n.commentId, n.text, n.inReplyToCommentId, u.id as byUserId, 
    ( SELECT COUNT(nu.id)
    FROM notificationUsers AS nu
    WHERE nu.notificationId = n.id ) as detail1,
    ( SELECT nu2.userId
    FROM notificationUsers AS nu2
    WHERE nu2.notificationId = n.id ORDER BY nu2.id DESC LIMIT 1 ) as latestUserId FROM notifications AS n LEFT JOIN userData AS u ON n.byUserId = u.id
    WHERE n.userId = :userId ORDER BY n.time DESC');
$qry->bindParam(':userId', $_USERDATA["userId"], PDO::PARAM_INT);
$qry->execute();

$notificationsArray = $qry->fetchAll(PDO::FETCH_ASSOC);


$returnValue = array();
$returnValue["status"] = "1";
$returnValue["title"] = "Success";
$returnValue["message"] = "Downloaded notifications";
$returnValue["data_notifications"] = $notificationsArray;
exit(json_encode($returnValue));



?>

...

更新 1

所以我决定做以下事情:

将每个未共享的文件放在一个文件夹中,如下所示:

/api/v1.0/file.php

但是每个资源(例如图像)都在 API 之外

/resources/images/profilepictures/image.jpg

如果我做一个小改动,我只会更新api/v1.0/ 文件夹中的文件。

然后,所有使用 Application v1.1 的用户都在请求 myapp.com/api/v1.1/,但我将他们重定向到 api/v1.0/ 在那里我可以向用户提供正确的数据(取决于请求是否从 v1.0 或 v1.1)

如果版本加起来并且我发布了更大的更新,我将创建一个名为 v2.0 的新文件夹,这样就可以了...

或者你怎么看?我该怎么做?

【问题讨论】:

标签: php api versioning


【解决方案1】:

您正在定义您的架构,以确保您的设计面向未来,这是很好的第一步。

如果您使用 Laravel 或 Symfony 之类的框架,您可以保持 Models 和 Helpers 目录通用,同时使用 v1.x、v2.x 等子目录对 Controllers 目录进行版本控制。

如果您使用路由机制,它可以让您的生活变得轻松,例如,假设您的 v1.0 有 50 个 API 端点,并且您计划修改其中的 5 个以实现 v1.2 不向后兼容,在在这种情况下,其余 45 个 API 端点仍然与 v1.0 相同,并且您不想在 v1.2 目录中复制它们。

<?php

$versions = ["v1.0", "v1.2"];

route("/api/v1.0/foobar", "Controllers/v1.0/FoobarController@doSomething");
route("/api/v1.0/footar", "Controllers/v1.0/FoobarController@doTar");

route("/api/v1.2/foobar", "Controllers/v1.2/FoobarController@doSomething");

function route($endpoint, $controller)
{
    // Logic to call function of a respective class/file 
    // and call previous version of an API if function/endpoint is not redefined in current version
}
?>

所以在上述情况下,当客户端调用 /api/v1.2/footar 时,它应该为 API 使用者执行 /api/v1.0/footar。

希望对你有帮助。

【讨论】:

    【解决方案2】:

    许多其他答案建议使用 frameworks(Symfony 等),它们有优点(更多的即插即用)和缺点(它们有 很多 样板可用于设置)。我将重点介绍针对此问题的纯原生 PHP 解决方案,目标如下:

    1.保持代码库尽可能小(很少重复)
    2。支持最简单的实现(与框架解决方案相比的主要优势,因为样板更少)

    这将是解决方案的示例实现。 index.php(第一个文件):

    <?php
    require_once("path/to/config");
    require_once("path/to/helpers/that/are/used/by/both/apis");
    
    //This is where we decide where to route the request
    if(strpos('/v1/', $_SERVER["REQUEST_URI"])) {
        //This is api v1 so use api v1
        require_once("path/to/api/objects/1.0");
    } else {
        //This is api v2 (or the default since most recent)
        require_once("path/to/api/objects/2.0");
    }
    //Use the classes just imported to handle the request:
    $apiObject = new Responder(); //Imported from one of the two api versions
    echo $apiObject->handle(); 
    
    ?>
    

    上面的代码根据解析 URL 来区分这两个 API,并为每个 API 导入不同的类。

    对于每种类型的导入 API 文件,它们都可以扩展相同的父 API 类(减少总代码),具有完全相同的方法名称,并且它们的部分或全部方法的行为不同。

    对于真正简单甚至更复杂的后端 PHP 服务来说,这是一个更优雅的解决方案。

    【讨论】:

    • 请在第一个条件后面加上括号
    • 非常感谢@Winner1
    【解决方案3】:

    正如我所见,您想在没有任何框架的情况下用纯 PHP 编写您的 API。 我只是想带你走上正确的道路,给你一些用 PHP 开始服务器端开发的愿景。

    • 首先选择一个框架来编码。也许CodeIgniter,它是一个易于使用的[阅读以下内容]
    • 研究大多数框架都支持的 MVC 设计模式,当您想要维护或扩展现有代码时,它会让您的生活变得轻松 - 这是必要且足够简单的,不要害怕
    • 为了向后兼容而克隆整个项目是多余的(假设您只想修复数据库访问层(模型/存储库)中的错误,您应该对所有其他版本重复此操作) - 您可以通过仅克隆控制器来实现并定义新路由 - [由于设计模式,您在控制器层的业务逻辑中仍然存在先前的问题]
    • 如果您想要一种更强大的方法,您应该开始使用带有服务层(又名 MVCS)的 Repository 模式 进行编码,并使用 Laravel 来防止不同版本控制器层中的代码耦合并保持您的服务层共享业务逻辑(与控制器分离)
    • 通过使用文档注释标签(如@deprecated 和@since)在代码中记录重要内容,以指定何时弃用或添加某些功能(因为在相关版本退役之前,您无法清除弃用的功能。)[检查this link得到想法]
    • 关于版本控制标准的研究 - SEMVER
    • 不要使用纯 PHP 编码

    【讨论】:

    • 嗯,很有趣。我已经阅读了您的答案,我阅读了您链接的版本控制标准,这非常有用,谢谢,您向用户提出的带有框架的 MVC 设计模式也很有用。一件事是:我没有意见。我的 iOS 应用程序只需要数据。你怎么看,我还是应该坚持使用框架,还是在这种情况下纯 PHP 就足够了?
    • 绝对需要一个框架来工作。这些类型的设计模式的目的是在编程中分离代码层。即使您没有任何视图层,您也可以使用 MVC 设计模式,仅用于 API ..
    • 我投反对票纯粹是因为你说的是​​ Code Igniter 而不是 Symfony,而 Symfony 的大部分互联网都是建立在其之上的。
    • 亲爱的@Lulceltech。首先,CI项目的市场份额与 Symphony 相当,甚至比 Symphony 还要大。其次,正如你所看到的,这个问题不是关于框架竞赛或“什么是最好的 PHP 框架”,我写了一个通知为什么我建议 CI,为什么 Laravel 可能是一个不错的选择等等......我会再说一遍从像 CI 这样的快速入门开始比普通 PHP 更好。但是还有更多的框架如 Laravel、Symphony、Yii、CakePHP、Lumen、Phalcon 等可供选择。
    • @Rancbar 你了解 Laravel、wordpress,还有很多其他的 CMS 和框架是建立在 Symfony 之上的吗? Symfony 为互联网的很大一部分提供动力。
    猜你喜欢
    • 2020-05-15
    • 1970-01-01
    • 2014-03-25
    • 2017-05-18
    • 2011-10-11
    • 1970-01-01
    • 2012-03-01
    • 2014-10-26
    相关资源
    最近更新 更多