Come utilizzare API RESTful esterne con Symfony?


10

Stiamo costruendo un'architettura Microservice per i nostri progetti, con applicazioni Symfony principalmente front-end che interagiscono con le API RESTful back-end.

Il problema è che questo approccio sta rompendo la gestione delle entità di Symfony basandosi pesantemente su Doctrine con il database. Laddove Symfony di solito gestisce entità con Doctrine, automatizzando gran parte del lavoro, questo non può essere riprodotto facilmente quando dobbiamo accedere a dati esterni dalle API.

Ad esempio, con un'entità client:

  • Usando Doctrine, dobbiamo solo definire la nostra classe Client, ed è ora facile creare, aggiornare, recuperare i nostri clienti
  • Utilizzando l'approccio API REST, i client sono accessibili tramite l'API, ma abbiamo molto lavoro per definire come il client viene creato (POST), aggiornato (PUT), recuperato (GET), ecc.

Da notare che i client vengono utilizzati da diverse applicazioni, non solo dall'app front-end, quindi dall'API dedicata.

Dovremmo creare classi con metodi simili a entità che nascondano la complessità delle chiamate API, importando tutti i dati API localmente e accedendoli tramite Doctrine o in altro modo?


Sono nella stessa barca come te. Consumo di API esterne con client generati dalle specifiche OpenApi / Swagger. Chiedendo quali siano le migliori pratiche per il "ciclo di vita" dei consumi, le operazioni sul greggio, i parametri e la generazione di filtri. Attualmente sto espandendo la mia ricerca per includere qualsiasi approccio, indipendentemente dal fatto che sia specifico di Symfony o meno.
monte

Avendo lavorato su questo problema per diversi mesi e tornando su questa domanda, entrambe le risposte finora forniscono una soluzione simile: astrarre le chiamate API con popo. Questo è il modo in cui abbiamo finito per usare, sebbene esistano altre soluzioni. In contesti di comunicazione API Webapp <> simili, l'utilizzo del livello di astrazione che nasconde le chiamate API da Webapp sembra una buona soluzione. Con l'ascesa di microservizi e approcci basati sulle API, senza dubbio emergeranno le migliori pratiche e gli strumenti correlati per risolvere quello che sembra essere un problema comune.
Pierre B.

Qui è stato applicato un approccio simile. La logica aziendale è ora contenuta in un livello 'azione', a cui non importa se è l'API REST o un comando cli che lo chiama. Il design esagonale di Alistair Cockburn è stato un ottimo punto di partenza nel nostro caso: alistair.cockburn.us/Hexagonal+architecture
upstream

Risposte:


2

Ho realizzato un progetto basato su symfony che utilizza un'API esterna (JSON); quello che ho fatto è stato creare una libreria client indipendente ("libreria client" - un pezzo di software, pacchetto compositore), con il proprio set di entità (POPO); si integra con il framework utilizzando le interfacce fornite da Symfony (ad esempio, semplicemente creando un provider utente personalizzato ).

Il client rende le chiamate http "dietro le quinte", il che è importante per le future capacità di test. Non vuoi esporre il modo in cui comunichi con l'origine dati e non vuoi che i tuoi test facciano affidamento su API live.

Interfaccia della libreria client (esempio come potrebbe apparire):

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

La libreria client utilizza Guzzle per la comunicazione e il componente Doctrine Cache per la memorizzazione nella cache dei risultati. La mappatura tra oggetti entità e json è stata fatta da mappatori, che una volta scritti non cambiavano molto spesso (o evento). In questo caso, suggerirei di utilizzare il serializzatore JMS per una trasformazione automatizzata da e verso JSON (suppongo che tu usi JSON).

Avrai bisogno di un buon meccanismo di memorizzazione nella cache e di archiviazione locale, come Redis. Effettuare chiamate API per ogni richiesta di app interromperà il server e rallenterà drasticamente l'applicazione. È molto importante capire come funzionano le cache http. Se l'API non utilizza le intestazioni di memorizzazione nella cache (o la utilizza in modo oscuro), sarà molto difficile e dispendioso in termini di risorse tenere traccia delle modifiche.

Dovresti anche pensare a come dovrebbe comportarsi il client in caso di interruzione della connessione: il client dovrebbe utilizzare i dati bloccati? Sarebbe una buona idea usare un server proxy tra la tua app e l'API. In questo caso il proxy (come Varnish) potrebbe velocizzare le tue richieste e anche aggiornare i dati bloccati in background senza rallentare l'app. Manterrà anche il tuo sito Web online in caso di errore dell'API. Nel frattempo potresti non essere in grado di scrivere dati, ma i tuoi utenti saranno comunque in grado di sfogliare i dati memorizzati nella cache.

E parlando di Dottrina, vedi la " Legge dello strumento ".


1

Doctrine è un livello di accesso al database. Non vuoi accedere a un database, ma api. Puoi ancora creare un'entità, ma poi come un semplice oggetto che non deve estendere nulla al nostro attrezzo (un popo). Dovrebbe avere un repository che implementa tutti i metodi CRUD. In questo caso chiama l'API anziché il database. Creerei un'interfaccia per questo. Non deve essere diverso per l'applicazione da utilizzare, tranne per il fatto che è necessario tener conto ovunque che un micro servizio potrebbe non rispondere.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.