昨年、PHP-FIGはPSR-7標準を採用しました。これは、HTTPメッセージの操作方法を説明しています。 この標準とその応用に関する良い記事は、Habréにありました。 PSR-7は大きな進歩ですが、HTTPクライアントの一般的なインターフェイスである論理的な継続性が欠けています。 欠落しているコンポーネントの作成は、 PHP-HTTPグループを占有しました 。
問題
PSR-7インターフェースを使用すると、HTTP要求および応答の特定の実装を無視できます。 ただし、自分でリクエストを行う必要がある場合のみです。 ここでも、どの実装にもしっかりと接続する必要があります。 アプリケーションを作成するとき、これは自然なことです。 図書館を書くとき、それはまったく良くありません。 たとえば、当社のサイトは、公式および非公式のライブラリとSDKを使用して、5つのサードパーティサービスとやり取りしています。 そして、それぞれが独自のHTTPクライアントを使用します。 誰かがGuzzle、誰かがcURL、誰かがただfile_get_contents。 1つのアプリケーションで5つの異なるHTTPクライアント! それぞれに独自の特性、独自の制限、独自のカスタマイズオプションがあります。 この動物園を、すべてのアプリケーションコンポーネントとライブラリで使用される単一のクライアントに置き換えるとよいでしょうか?
Httpplug
このグループの主な開発は、アプリケーションで使用される特定のHTTPクライアントからライブラリを抽象化できるHttplugインターフェイスのセットです。 既にいくつかのクライアント実装(ソケット、cURL)とアダプター(Guzzle、React)があります。 さらに、プロジェクトはSymfonyのパッケージを含む多くのサポートパッケージを開発しました。
そして、これはすべて開発者に何を与えますか?
図書館アプリケーション
HTTP要求を満たす必要があるライブラリを作成している場合、特定のクライアントにバインドする必要はなくなりました。 代わりに、「composer.json」で指定できます:
{ "require": { "php-http/client-implementation": "^1.0" }, "require-dev": { "php-http/curl-client": "^1.4" } }
php-http/client-implementation
は、ライブラリにHTTPクライアントphp-http/curl-client
が必要であることを示しphp-http/curl-client
-デバッグ中に使用でき、開発に必要なすべてのインターフェイスとクラスをプルする任意の実装。 デバッグには、 guzzlehttp / psr7などのPSR-7の実装も必要になる場合があります。
ライブラリが何らかのAPIで動作し、メインコンポーネントがこのAPIのクライアントであるとします。
class ApiClient { /** * HTTP. */ private $httpClient; /** * HTTP. */ private $requestFactory; public function __construct(HttpClient $httpClient, RequestFactory $requestFactory) { $this->httpClient = $httpClient; $this->requestFactory = $requestFactory; }
ここに:
- HttpClient-実際には、HTTPクライアント( php-http / httplugパッケージ );
- RequestFactoryは、PSR-7リクエスト( php-http / message-factoryパッケージ)を作成できるファクトリです。
これで、リクエストを行う必要がある場合、次のように記述できます。
/** * @param string $uri * @param string $payload */ public function apiCall($uri, $payload) { $request = $this->requestFactory->createRequest('POST', $uri, ['content-type' => 'foo/bar'], $payload); $response = $this->httpClient->sendRequest($request); // ... }
概して、必要なのはそれだけです。 ライブラリは特定のクライアントに依存せず、ユーザーは自分に最適なクライアントを選択できます。 これがどのように行われるかを見てみましょう。
アプリケーションの使用
上記のライブラリを使用するには、アプリケーション開発者はクライアント実装の1つであるPSR-7実装を選択し、それらをライブラリに接続する必要があります。
$ composer require php-http/guzzle6-adapter $ composer require /
guzzle6-adapter
はguzzlehttp/psr7
を自動的に強化するため、個別に指定する必要はありません。
まだguzzlehttp/psr7
へのguzzlehttp/psr7
としてphp-http / messageが必要guzzlehttp/psr7
:
$ composer require php-http/message
次に、クライアント、アダプターを作成し、ファクトリーを要求して、最後の2つをApiClientコンストラクターに渡す必要があります。
use GuzzleHttp\Client as GuzzleClient; use Http\Adapter\Guzzle6\Client as GuzzleAdapter; use Http\Message\MessageFactory\GuzzleMessageFactory; $config = [ // ... ]; $guzzle = new GuzzleClient($config); $adapter = new GuzzleAdapter($guzzle); $apiClient = new ApiClient($adapter, new GuzzleMessageFactory);
ApiClientはすぐに使用できます。 HTTPクライアントを必要とするすべてのコンポーネントに同じオブジェクト($アダプター)を渡すことができます。
将来、Guzzleを別のものに置き換える必要がある場合は、コードのこの部分を書き換えるだけで済みます。 HTTPで動作する他のすべてのコードに手を加える必要はありません。
他に何が面白いですか?
完全なパッケージとその機能は公式ドキュメントに記載されていますが、私の意見では興味深いものだけを紹介します。
非同期リクエスト
特別なHttpAsyncClientインターフェイスを使用すると、 promiseエンジンを使用してリクエストを非同期に実行できます 。
実装の自動検出(検出)
Puliベースの自動検出システムにより、特定の実装を参照せずに顧客および工場のオブジェクトを受け取ることができます。
$httpClient = HttpClientDiscovery::find();
拡張システム(プラグイン)
すべてまたは一部のHTTPクライアントにエンドツーエンド機能を追加できます。 以下に例を示します。
Httpplugbundle
複数のSymfonyクライアント、拡張機能、デバッグパネルのサポートを含むSymfonyのパッケージ 。
結論として
このプロジェクトはその道のりの始まりですが、戦闘状態で使用するのに十分安定しています。 彼らは意欲的な目標を設定しました-PSRの推奨としての開発の受け入れを達成すること。