web-dev-qa-db-ja.com

symfonyで外部RESTful APIを利用する方法は?

主にフロントエンドのSymfonyアプリケーションがバックエンドのRESTful APIと対話して、プロジェクトのマイクロサービスアーキテクチャを構築しています。

問題は、このアプローチがDoctrineデータベースに大きく依存しているSymfonyエンティティ管理を壊していることです。Symfonyは通常、Doctrineでエンティティを処理し、ほとんどの作業を自動化しますが、必要なときに簡単に再現できません。 APIから外部データにアクセスします。

たとえば、クライアントエンティティの場合:

  • Doctrineを使用すると、Clientクラスを定義するだけで済み、クライアントの作成、更新、取得が簡単になりました
  • REST APIアプローチを使用すると、APIを介してクライアントにアクセスできますが、クライアントの作成(POST)、更新(PUT)、取得(GET)、等.

クライアントは、フロントエンドアプリだけでなく、専用APIだけでなく、いくつかのアプリケーションで使用されていることに注意してください。

API呼び出しの複雑さを隠すエンティティのようなメソッドでクラスを作成し、すべてのAPIデータをローカルにインポートして、Doctrineを通じて、または他の方法でそれらにアクセスする必要がありますか?

10
Pierre B.

外部API(JSON)を使用するsymfonyベースのプロジェクトを作成しました。私がやったことは、独立したクライアントライブラリ(「クライアントライブラリ」-ソフトウェアの一部、composerパッケージ)、独自のエンティティ(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キャッシュコンポーネントを使用します。エンティティオブジェクトとjsonの間のマッピングはマッパーによって行われ、一度書き込まれると、あまり変更されませんでした(またはイベントこの場合、JSONとの間の自動変換にはJMSシリアライザーを使用することをお勧めします(JSONを使用すると想定しています)。

Redisのような優れたキャッシュメカニズムとローカルストレージが必要です。各アプリリクエストでAPI呼び出しを行うと、サーバーが強制終了され、アプリケーションの速度が大幅に低下します。 httpキャッシュの仕組みを理解することは非常に重要です。 APIがキャッシングヘッダーを使用しない場合(またはあいまいな方法で使用する場合)、変更を追跡することは非常に難しく、リソースを消費します。

また、接続が切断された場合のクライアントの動作を検討する必要があります。クライアントは停止したデータを使用する必要がありますか?アプリとAPIの間でプロキシサーバーを使用することをお勧めします。この場合、プロキシ(Varnishなど)はリクエストを高速化し、アプリを遅くすることなく、バックグラウンドで停止したデータを更新することもできます。また、APIに障害が発生した場合にウェブサイトをオンラインに保ちます。それまでの間、データを書き込めない可能性がありますが、ユーザーは引き続きキャッシュデータを閲覧できます。

Doctrineについて言えば、「 楽器の法則 」を参照してください。

2
Jacek Kobus

Doctrineはデータベースアクセスレイヤーです。データベースにアクセスするのではなく、APIにアクセスします。エンティティを作成することはできますが、実装を拡張する必要のない単純なオブジェクト(popo)として作成できます。すべてのCRUDメソッドを実装するリポジトリが必要です。この場合、データベースではなくAPIを呼び出します。そのためのインターフェースを作成します。マイクロサービスが応答しない可能性があるすべての場所を考慮する必要があることを除いて、アプリケーションが使用するために違和感を感じる必要はありません。

1
winkbrace

参考までに、v4.3用のHttpClientコンポーネントがあります。

https://symfony.com/blog/new-in-symfony-4-3-httpclient-component

0
Fred Flint