如何通过Symfony使用外部RESTful API?


10

我们正在为我们的项目构建微服务架构,其中大多数前端Symfony应用程序与后端RESTful API进行交互。

问题在于,这种方法打破了严重依赖带有数据库的Doctrine的Symfony实体管理。Symfony通常使用Doctrine处理实体,从而使大部分工作自动化,而当我们必须从API访问外部数据时,就很难轻松地重现这一点。

例如,对于客户实体:

  • 使用Doctrine,我们只需要定义Client类,现在就可以轻松地创建,更新和检索客户
  • 使用REST API方法,可以通过API访问客户端,但是我们还有很多工作来定义如何创建(POST),更新(PUT),检索(GET)客户端等。

需要注意的是,客户端被多个应用程序使用,不仅是前端应用程序,还有专用的API。

我们是否应该使用类似于实体的方法来创建类,从而隐藏API调用的复杂性,在本地导入所有API数据并通过Doctrine或其他方式访问它们?


我和你在同一条船上。与从OpenApi / Swagger规范生成的客户端一起使用外部API。想知道有关消费“生命周期”,粗粒操作,参数和过滤器表单生成的最佳实践。目前,无论我是否特定于Symfony,我的搜索范围都在扩大,以包括任何方法。
2016年

在解决了这个问题几个月之后,又回到了这个问题,到目前为止,两个答案都提供了一个类似的解决方案:使用popo抽象api调用。这是我们最终使用的方法,尽管还存在其他解决方案。在类似的Webapp <> API通信上下文中,使用抽象级别隐藏来自Webapp的API调用似乎是一个很好的解决方案。随着微服务和API领先方法的兴起,毫无疑问,将出现相关的最佳实践和工具来解决似乎很常见的问题。
Pierre B.

在这里,采用了类似的方法。现在,业务逻辑包含在“操作”层中,该层不关心是REST api还是调用它的cli命令。在我们的案例中,Alistair Cockburn的六角形设计是一个很好的起点:alistair.cockburn.us/Hexagonal+architecture
上游

Answers:


2

我已经制作了一个使用外部API(JSON)的基于symfony的项目;我所做的是创建一个独立的客户端库(“客户端库”-一种软件,作曲家程序包),并带有自己的一组实体(POPO);它使用Symfony提供的接口(例如,通过简单地创建自定义用户提供程序)与框架集成。

客户端发出http调用“幕后”-这对于将来的测试功能很重要。您不想公开与数据源通信的方式,也不想测试依赖实时API。

客户端库界面(示例看起来如何):

class ApiClient {

   /**
    * @throws SomeApiException If credentials are invalid
    * @return ApiUser
    */
   public function authenticate($username, $password);

   /**
    * @return ApiUser
    */
   public function findUserByEmail($email);

   /**
    * @throws SomeApiException If email is invalid
    * @return void
    */
   public function changeUserEmail(User $user, $newEmail);
}

客户端库内部使用Guzzle进行通信,并使用Doctrine Cache组件来缓存结果。实体对象和json之间的映射是由映射器完成的,该映射器一旦写入,就不会经常更改(或根本不会更改)。在这种情况下,我建议使用JMS序列化器进行JSON的自动转换(假设您使用JSON)。

您将需要一个良好的缓存机制和本地存储,例如Redis。在每个应用程序请求上进行api调用将杀死您的服务器,并严重降低应用程序的速度。了解http缓存的工作方式非常重要。如果您的api不使用缓存标头(或以晦涩的方式使用它),跟踪更改将非常困难且消耗资源。

您还将要考虑如果连接断开,客户端应如何处理-客户端应该使用停顿的数据吗?在您的应用程序和API之间使用一些代理服务器是一个好主意。在这种情况下,代理(如Varnish)可以加快您的请求,并在后台刷新停顿的数据而不会降低您的应用程序的速度。如果API出现故障,它还将使您的网站保持在线状态。在此期间,您可能无法写入数据,但是您的用户仍将能够浏览缓存的数据。

谈到教义,请参见“ 工具法则 ”。


1

原则是数据库访问层。您不想访问数据库,但要访问API。您仍然可以创建一个Entity,但是作为一个简单的对象,不必扩展我们的实现(popo)。它应该具有一个实现所有CRUD方法的存储库。在这种情况下,将调用API而不是数据库。我将为此创建一个接口。使用您的应用程序并不一定会有所不同,只不过您必须考虑微服务可能不响应的所有地方。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.