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固有のものであるかどうかに関係なく、あらゆるアプローチを含むように検索を拡大しています。
アップストリーム

数か月間この問題に取り組み、この質問に戻ってきましたが、これまでの両方の回答は同様の解決策を提供しています:popoでAPI呼び出しを抽象化します。他の解決策は存在しますが、それが私たちが最終的に使用した方法です。同様のWebアプリケーション<> API通信コンテキストでは、Webアプリケーションからの抽象化レベルの非表示API呼び出しを使用することは、良い解決策のようです。マイクロサービスとAPI主導のアプローチの台頭により、一般的な問題と思われるものを解決するための関連するベストプラクティスとツールが明らかになるでしょう。
ピエール

ここでは、同様のアプローチが適用されました。ビジネスロジックが「アクション」レイヤーに含まれるようになりました。これは、REST APIかそれを呼び出すcliコマンドかは関係ありません。Alistair Cockburnの六角形のデザインは、私たちの場合、すばらしい出発点でした:alistair.cockburn.us/Hexagonal+architecture
上流

回答:


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の間のマッピングは、一度作成されたマッパーによって行われました-それほど頻繁には変更されませんでした(またはイベントではまったく変更されません)この場合、JSONとの自動変換にJMSシリアライザーを使用することをお勧めします(JSONを使用すると想定しています)。

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

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

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


1

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


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.