Wie verwende ich eine externe RESTful-API mit Symfony?


10

Wir erstellen eine Microservice-Architektur für unsere Projekte, wobei hauptsächlich Front-End-Symfony-Anwendungen mit Back-End-RESTful-APIs interagieren.

Das Problem ist, dass dieser Ansatz das Symfony-Entitätsmanagement unterbricht, das sich stark auf Doctrine mit Datenbank stützt. Wenn Symfony normalerweise Entitäten mit Doctrine verarbeitet und den größten Teil der Arbeit automatisiert, kann dies nicht einfach reproduziert werden, wenn über die APIs auf externe Daten zugegriffen werden muss.

Zum Beispiel mit einer Client-Entität:

  • Mit Doctrine müssen wir nur noch unsere Client-Klasse definieren, und es ist jetzt einfach, unsere Clients zu erstellen, zu aktualisieren und abzurufen
  • Mit dem REST-API-Ansatz können Clients über die API aufgerufen werden. Wir müssen jedoch noch viel definieren, wie der Client erstellt (POST), aktualisiert (PUT), abgerufen (GET) usw. wird.

Zu beachten ist, dass Clients von mehreren Anwendungen verwendet werden, nicht nur von der Front-End-App, daher auch von der dedizierten API.

Sollten wir Klassen mit entitätsähnlichen Methoden erstellen, die die Komplexität der API-Aufrufe verbergen, alle API-Daten lokal importieren und über Doctrine oder auf andere Weise darauf zugreifen?


Ich bin im selben Boot wie du. Externe APIs mit Clients verwenden, die aus OpenApi / Swagger-Spezifikationen generiert wurden. Fragen Sie sich nach Best Practices für den Verbrauchslebenszyklus, Rohöloperationen, Parameter und die Erzeugung von Filterformularen. Derzeit erweitere ich meine Suche um alle Ansätze, unabhängig davon, ob sie Symfony-spezifisch sind oder nicht.
Upstream

Nachdem beide Antworten mehrere Monate an diesem Problem gearbeitet haben und auf diese Frage zurückgekommen sind, bieten sie bisher eine ähnliche Lösung: Abstrahieren von API-Aufrufen mit Popo. So haben wir es letztendlich gemacht, obwohl es andere Lösungen gibt. In ähnlichen Webapp <> API-Kommunikationskontexten scheint die Verwendung von API-Aufrufen auf Abstraktionsebene vor der Webapp eine gute Lösung zu sein. Mit dem Aufkommen von Microservices und API-Lead-Ansätzen werden zweifellos verwandte Best Practices und Tools entstehen, um ein scheinbar häufiges Problem zu lösen.
Pierre B.

Hier wurde ein ähnlicher Ansatz angewendet. Die Geschäftslogik ist jetzt in einer Aktionsebene enthalten, die sich nicht darum kümmert, ob es sich um die REST-API oder einen CLI-Befehl handelt, der sie aufruft. Das sechseckige Design von Alistair Cockburn war in unserem Fall ein guter
Upstream

Antworten:


2

Ich habe ein symfony-basiertes Projekt erstellt, das eine externe API (JSON) verwendet. Ich habe eine unabhängige Client-Bibliothek ("Client-Bibliothek" - eine Software, ein Composer-Paket) mit eigenen Entitäten (POPOs) erstellt. Die Integration in das Framework erfolgt über von Symfony bereitgestellte Schnittstellen (z. B. durch einfaches Erstellen eines benutzerdefinierten Benutzeranbieters ).

Der Client führt http-Aufrufe "hinter den Kulissen" durch - dies ist wichtig für zukünftige Testfunktionen. Sie möchten nicht offenlegen, wie Sie mit Ihrer Datenquelle kommunizieren, und Sie möchten auch nicht, dass Ihre Tests auf Live-API basieren.

Client-Bibliotheksschnittstelle (Beispiel, wie es aussehen könnte):

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);
}

Die Client-Bibliothek verwendet intern Guzzle für die Kommunikation und Doctrine Cache-Komponente zum Zwischenspeichern der Ergebnisse. Die Zuordnung zwischen Entitätsobjekten und json wurde von Zuordnern vorgenommen, die sich nach dem Schreiben nicht sehr oft (oder überhaupt nicht) geändert haben. In diesem Fall würde ich vorschlagen, den JMS Serializer für eine automatisierte Umwandlung von und nach JSON zu verwenden (ich gehe davon aus, dass Sie JSON verwenden).

Sie benötigen einen guten Caching-Mechanismus und lokalen Speicher wie Redis. Wenn Sie bei jeder App-Anfrage API-Aufrufe tätigen, wird Ihr Server zerstört und Ihre Anwendung drastisch verlangsamt. Es ist sehr wichtig zu verstehen, wie http-Caches funktionieren. Wenn Ihre API keine Caching-Header verwendet (oder diese auf unklare Weise verwendet), ist es sehr schwierig und ressourcenintensiv, die Änderungen im Auge zu behalten.

Sie sollten auch darüber nachdenken, wie sich der Client verhalten soll, wenn die Verbindung unterbrochen wird. Sollte der Client blockierte Daten verwenden? Es ist eine gute Idee, einen Proxyserver zwischen Ihrer App und der API zu verwenden. In diesem Fall kann der Proxy (wie Varnish) Ihre Anforderungen beschleunigen und blockierte Daten im Hintergrund aktualisieren, ohne Ihre App zu verlangsamen. Außerdem bleibt Ihre Website im Falle eines API-Fehlers online. In der Zwischenzeit können Sie möglicherweise keine Daten schreiben, aber Ihre Benutzer können weiterhin zwischengespeicherte Daten durchsuchen.

Wenn Sie von Lehre sprechen, lesen Sie das " Gesetz des Instruments ".


1

Doctrine ist eine Datenbankzugriffsschicht. Sie möchten nicht auf eine Datenbank zugreifen, sondern auf apis. Sie können immer noch eine Entität erstellen, aber dann als einfaches Objekt, das unser Gerät nicht erweitern muss (ein Popo). Es sollte ein Repository haben, das alle CRUD-Methoden implementiert. In diesem Fall wird die API anstelle der Datenbank aufgerufen. Ich würde eine Schnittstelle dafür erstellen. Es muss sich für Ihre Anwendung nicht anders anfühlen, außer dass Sie überall berücksichtigen müssen, dass ein Mikrodienst möglicherweise nicht reagiert.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.