PHPでHTTPリクエストを実行する5つの方法
読む所要時間: 25 分
HTTPリクエストは、特にPHPにおいて、最新のWebベースのアプリケーションを特徴付けるものです。開発者は、Google Cloud、Facebook、AWSなど、あらゆる種類の外部サービスやAPIを頻繁に操作する必要があります。極端に言えば、HTTPリクエストは、PHPの基礎の習得後に開発者が最初に学ぶことの1つになるかもしれません。少なくとも私の場合はそうでした。
そうは言うものの、最新の多くのソフトウェア開発言語と同様に、PHPでHTTPリクエストを実行する方法は複数あります。本稿では、PHPでHTTPリクエストを実行するための5つの方法を紹介します。加えて、それらの使用方法と、それぞれの長所と短所について説明します。詳細を説明するというよりは、それぞれについて広義に紹介していきます。
本稿で紹介するHTTPリクエストの実行方法は次のとおりです。
それぞれの方法で、FlickrのAPIを使用し、以下のようなオーストラリアのカカドゥ国立公園の画像を10枚ダウンロードします。
“カカドゥ国立公園のイエロー・ウォーター・ビラボンに沈む夕日、オーストラリア、ノーザンテリトリー州”(Geoff Whalan氏撮影、CC BY-NC-ND 2.0に基づく掲載許可)
必要条件
チュートリアルを完了するには、以下の項目が必要です。
- PHP 7.4以降(理想的にはバージョン8、cURLとOpenSSL拡張機能をインストールし、allow_url_fopenランタイム設定を有効にする)
- Composer(グローバルにインストール)
- Git(Composerを完全に機能させるために必要)
- Grep
- FlickrアカウントとFlickr APIキー
始める前に
このチュートリアル全体で5つのPHPスクリプトを作成しますが、開始する前に、次の項目を実行してください。
- プロジェクトディレクトリを作成する。
- PHP dotenvをインストールする。
- Flickr APIキーを.envファイルに追加し、誤ってサンプルコードに保存しないようにする。
最初の2つの手順を完了するには、以下の3つのコマンドを実行します。
次に、プロジェクトディレクトリに.envファイルを作成し、以下のコードを追加します。プレースホルダー(<FLICKR API KEY>
)をFlickr APIキーに置き換えます。
これで、次に進む準備ができました。
PHPのコア機能と拡張機能
最初に、PHPのコア機能と拡張機能の一部として利用可能なオプションについて説明します。
HTTP/Sストリームラッパー
PHPマニュアルからの引用:
HTTP GETメソッドを使用し、HTTP 1.0によるファイル/リソースへの読み取り専用アクセスを許可します。Host:
ヘッダーは、名前ベースの仮想ホストを処理するためのリクエストとともに送信されます。php.iniファイルまたはストリームコンテキストを使用してuser_agent文字列を設定した場合は、user_agent
もリクエストに含まれます。
ストリームはPHPのコアの一部であるため、ストリームの機能を利用するために多くの処理を実行する必要はありません。さらに、ストリームはfopenやfile_get_contentsなどのPHPのコア関数の多くと統合されています。このため、これらの使用を開始するために、サードパーティ製ライブラリやカスタム拡張機能をインストールする必要はありません。
裏を返せば、ストリームには、直感的なインターフェースもなければ、GuzzleHttpやSymfonyのHTTPクライアントなどのサードパーティ製ライブラリで提供されるヘルパーユーティリティメソッドもありません。さらに、ストリームは、
- 書き込み(POST、PUT、DELETE)ではなく、読み取り(GET)リクエストのみをサポートします。
- ユーザーエージェント、リダイレクト、ヘッダー、タイムアウト、プロキシなど、限られたコンテキストオプションのみをサポートします。そうは言うものの、これらを使用してできることは多くあります。
さて、起動して実行するまであまり時間はかかりません。http-stream.phpファイルをphp-httpディレクトリに作成し、以下のコードを貼り付けます。
上記のコードでは、最初にスクリプトでFlickrのAPIの操作とダウンロードした画像の保存に使用する定数を定義しています。
ストリームラッパーには、HTTPクエリ文字列を作成するネイティブな方法がないため、PHPのhttp_build_query関数を使用してHTTPクエリ文字列を作成します。代わりにネイティブの文字列の連結またはsprintfを使用することもできますが、http_build_query
の方がクリーンで直感的です。
次に、fopenを使用し、FlickrのAPIの読み取り専用HTTP接続を作成します。続いて、stream_get_contentsがリクエストのコンテンツを取得し、プレーンなPHPオブジェクトに逆シリアル化(unserialize
)します。
これらの2つの関数は、FlickrのAPIに対して写真検索リクエストを実行し、最大10枚の画像をダウンロードします。リクエストの結果がある場合は、file_get_contentsを呼び出してダウンロードし、file_put_contentsを使用してローカルファイルシステムに書き込みます。
PHPについては多くのことが言えますが、確かなことは柔軟性と適応性に優れていることです。既存のPHP関数を使用できることは確かなメリットですが、ストリームラッパーを使用すると、追加の依存関係が不要になるため、すぐにプログラムを起動して実行できます。
コードが機能することをテストする
コードを記述したら、コードをテストして機能することを確認します。以下のコマンドを実行します。
次のような出力が表示されます。
コマンド実行後、photosディレクトリを見ると、10個のJPEG(.jpg)ファイルが表示されているはずです。
PHPのcURL拡張機能
次に、PHPのcURL拡張機能を使用して同じことを実行する方法を紹介します。始める前に、次のコマンドを実行し、PHPランタイムでcURL拡張機能が使用可能であることを確認してください。
拡張機能をインストールして有効にすると、「cURL support => enabled」とターミナルに出力されます。curl.phpの名前のプロジェクトディレクトリに新しいファイルを作成し、以下のコードをペーストします。
最初に、cURLセッションを初期化するcurl_initを呼び出します。これにより、残りのコードがHTTPリクエストを実行するために必要なハンドルが提供されます。次に、2つのオプションが設定されます。
CURLOPT_RETURNTRANSFER
: リクエストをすぐにエコーアウトするのではなく、リクエストの結果を返すようにcURLに指示します。CURLOPT_URL
: リクエストするURLを設定します。
これらのオプションは両方とも個別に設定されています。ただし、以下の例のように、curl_setopt_arrayを使用し、1回の呼び出しで設定することもできます。
cURLを設定すると、curl_execを呼び出してFlickr APIにリクエストが送信され、結果が$result
に保存されます。その後、前述の例のように、プレーンなPHPオブジェクトにレスポンスが逆シリアル化され、curl_closeを呼び出してcURLセッションが閉じられ、関連するすべてのリソースが解放されます。
レスポンスが返されると、コードは処理を繰り返し、10枚の画像をそれぞれダウンロードします。このプロセスはストリームサンプルとかなり似ており、ダウンロードコードを逐語的に使用する方法もありました。しかし、ここでは、cURL固有の実装について示したいと考えました。
この例では、コードを実行すると、書き込み用のファイルハンドルを開き、ファイルコンテンツをダウンロードして新しいファイルに書き込み、curlセッションとファイルハンドルの両方を閉じます。
画像データをSTDOUTではなくファイルに書き込むためのcurl_setopt($ch, CURLOPT_FILE, $fp);
を呼び出すことにより、画像データをファイルに簡単に書き込むことができます。
この例では、cURL拡張機能がストリームラッパーよりもHTTPリクエストの作成にどのように適合しているかを示しています。また、cURL拡張機能が高度に設定可能であり、高機能であることも示しています。さらに、事前定義された定数は、論理的で直感的です。
他に注目すべき点は、GuzzleHttpやSymfonyのHTTPクライアントなどの多くのサードパーティパッケージが内部でcURL拡張機能を使用していることです。cURL拡張機能はさまざまなツールで使用されており、あなたも、すでに使用している可能性があります。
サードパーティのPHP HTTPパッケージ
ここまで、PHPでHTTP/Sリクエストを実行する2つのネイティブな方法を見てきました。次に、最も有名な3つのサードパーティパッケージを使用して実行する方法についてご紹介します。
GuzzleHttp
Michael Dowling氏が作成したGuzzleHttpは、本稿で取り上げる3つのサードパーティ製ライブラリの中で最も有名であり、広く利用されています。
少し雑学的なことになりますが、LaravelのHTTPクライアントを使用している場合は、内部でGuzzleHttpを使用していることをご存知でしたか?詳細については、Laravelのドキュメントを参照してください。
ライブラリをインストールするには、プロジェクトのルートディレクトリで以下のコマンドを実行します。
次に、プロジェクトディレクトリにguzzlehttp.phpファイルを作成し、以下のコードをペーストします。
このサンプルは前の2つより少し長めですが、必ずしも悪いことではありません。最初に、一連のリクエストオプションを含む配列を初期化します。
debug
: デバッグ出力を有効にします。query
: この配列は、リクエストのクエリ文字列の作成に使用されるため、http_build_query
を呼び出す必要がありません。
次に、新しいClient
オブジェクトを初期化し、キー/値のペア1組(base_uri
)を含む連想配列をコンストラクタに渡します。このキーの値は、オブジェクトを使用するすべてのリクエストの前に付加されるベースURLです。
Clientオブジェクトが初期化されると、オブジェクトのrequest
メソッドを呼び出してリクエストを実行し、次の3つのパラメーターを呼び出しに渡します。
- 使用するHTTPメソッド(
GET
) - リクエストのパス(
/services/rest
) - リクエストデータの連想配列(
$requestData
)
次に、リクエストの結果を取得し、$response->getBody()->getContents()
の結果をPHPのunserialize
関数に渡して結果をPHPオブジェクト表現に逆シリアル化します。これは前の2つの例と似ています。
その後、画像を写真ディレクトリにダウンロードします。これはストリームラッパーの例と似ていますが、重要な違いがあります。file_get_contents
とfile_put_contents
の組み合わせを使用する代わりに、$client->get
の呼び出しの2番目のパラメーターとして配列が提供されているため、Guzzleは1回の呼び出しだけでファイルをダウンロードできます。
配列のsink
オプションは、sink
の値で指定されたファイルにレスポンスの内容を書き込むようにGuzzleに指示します。sink
が指定されていない場合、php://tempストリームラッパーを使用して、レスポンスが一時的にファイルに保存されます。
この例は、カスタムライブラリがPHPのネイティブ機能より優れていることを示しています。カスタムライブラリには、HTTP/Sリクエストの作成専用に設計された論理的で直感的なクラス、メソッド、メソッドパラメーターがあり、作業が簡素化されます。
前述の例よりも長くなりますが、一般的に、PHPストリームまたはcURL拡張機能を使用するよりもGuzzleを使用する方が私はメリットが多いと思います。
Guzzleに関する決定的なメリットについて2つ紹介します。
- Guzzleでは、PSR-7(HTTPメッセージインターフェイス)とPSR-18(HTTPクライアント)の両方を実装し、これらの規格を利用するコードやフレームワークとの相互運用が可能です。
- Guzzleのドキュメントは分かりやすいです。ドキュメントが分かりやすければ、ライブラリを快適に使用できます。
Httpful
次に、Httpfulについてご紹介します。ドキュメントからの引用を紹介します。
Httpfulは、HTTP通信の健全性の向上を目的とした、チェーン化可能なシンプルで読みやすいPHPライブラリです。これにより、開発者はcurl set_opt
ページを検索する代わりに、APIの操作に集中できるため、理想的なPHP RESTクライアントになります。
以下はRequest
クラスに関する説明から抜粋したものであり、上記の引用を補強しています。
簡潔な構文を損なうことなく、読みやすさに重点が置かれています。
Httpfulライブラリをインストールするには、以下のコマンドを実行します。
次に、プロジェクトディレクトリにhttpful.phpファイルを作成し、以下のコードをペーストします。
このコードでは、最初にhttp_build_query
を使用してクエリ文字列を作成します。次に、これをBASE_URL
定数と連結し、Flickrに送信するリクエストURLを作成します。続いて、URLがRequest
のget
メソッドへの静的呼び出しに渡され、FlickrのAPIにGETリクエストが送信されます。
Request
は、ライブラリを使用してリクエスト実行するクラスです。post
、patch
、delete
、options
、head
など、get
以外にも、さまざまなメソッドをサポートしています。
また、次のようなメソッドも用意されています。
attach
(ファイルを添付)addHeader/s
(リクエストにヘッダーを追加)basicAuth/digestAuth
(認証)mime
(Content-TypeヘッダーとExpectedヘッダーを設定)followRedirects
(リダイレクトリクエストをフォロー)
前述の例と同様に、レスポンスの本文($response->body
)は、本文が使用可能な場合、プレーンなPHPオブジェクトに逆シリアル化されます。
画像をダウンロードするためのコードは、file_put_contents
を使用してファイルをローカルファイルシステムに書き込む前述の例と似ています。これを行うメソッドがライブラリで提供されていないためです。
Httpfulは、本稿でご紹介する3つのライブラリの中で最も簡単な方法と思われます。GuzzleHttpと多くの共通点がありますが、異なる部分もあります。連想配列をクエリ文字列に変換することはできませんが、メソッドは直感的かつ論理的です。インターフェースは使いやすく、リクエストを素早く簡単に作成して送信できます。
また、ライブラリがPHPのcURL拡張機能に基づいている点は特に注目すべきです。これにより、cURL拡張機能の信頼性が向上し、高機能の優れたツールを作成できます。
SymfonyのHTTPクライアント
最後に、SymfonyのHTTPクライアントについて見てみます。ドキュメントからの引用を紹介します。
HttpClientコンポーネントは、PHPストリームラッパーとcURLの両方をサポートする低レベルのHTTPクライアントです。APIを使用するユーティリティを提供し、同期と非同期操作をサポートします。
インストールするには、以下のコマンドを実行します。
次に、プロジェクトディレクトリにsymfony.phpファイルを作成し、以下のコードをペーストします。
このコードは、GuzzleHttpの例と同様に、リクエストデータの連想配列を定義することから始まります。前例と同様に、デバッグモードを有効にするためのdebug
と、クエリ文字列を作成するためのquery
を定義します。
次に、HttpClient
の静的なcreate
メソッドを呼び出して、リクエストを実行するHTTPクライアントをインスタンス化し、すべてのリクエストで使用されるデフォルトのリクエストオプションを渡します。
続いて、$client
のrequest
メソッドを呼び出してリクエストを作成します。ここでは、HTTPメソッドGET
、ベースリクエストのURLBASE_URL
とクエリデータを指定し、レスポンスは$response
に保存されます
この方法は前述の例とは少し異なり、最初にレスポンスのステータスコード(getStatusCode
)とcontent-type
ヘッダー($response->getHeaders()['content-type'][0]
)を取得してから、レスポンス本文を取得してプレーンなPHPオブジェクトに逆シリアル化します($response->getContent()
)。
その後の画像のダウンロード方法は、前述の例とほぼ同じです。Httpfulの例と同様に、ファイルをローカルファイルシステムに書き込むメソッドはライブラリで提供されていないため、file_put_contents
を使用してこの処理を実行します。
少し使用してみると、SymfonyのHTTPクライアントは、機能性、表現力、直感性の点でGuzzleHttpに匹敵することが分かります。クラス、メソッド、パラメーターには意味のある名前が付けられており、連想配列からクエリ文字列を簡単に作成できるなど、使いやすいライブラリです。これにより、HTTP/Sリクエストの作成に必要な労力が大幅に簡素化されます。
PHPでHTTPリクエストを実行する5つの方法
ここまで、PHPのHTTP/Sストリームラッパー、PHPのcURL拡張機能、GuzzleHttp、Httpful、SymfonyのHTTPクライアントを使用して、HTTPリクエストを作成する方法について見てきました。また、それぞれの使用例と各アプローチのメリットについても簡潔に説明しました。
ここで取り上げた5つのオプションは、どのプロジェクトでも使用できますが、経験上、プロジェクトが大規模で複雑になるほど、サードパーティ製パッケージを使用した方が適切な場合が多いです。私のお勧めはGuzzleHttpです。
サードパーティ製パッケージにより、効率性と快適性が向上する可能性があり、開発の時間を大幅に短縮できます。そうは言うものの、誤解を恐れずに言えば、PHPのcURL拡張機能やHTTP/Sストリームラッパーがあれば必要な機能はすべ揃うでしょう。使用するツールは少ない方がよい場合がありますよね。
最後、この記事の執筆にあたり、調査中にツイートにフィードバックをくれたすべての人に感謝申し上げます。いただいたフィードバックは、記事の執筆と推敲に大変参考になりました。
コーディングを楽しみましょう!あなたが何を構築されるか、とても楽しみです。
Matthew Setterは、Twilio VoicesチームのPHP編集者兼(もちろん)PHP開発者です。彼は、Mezzio EssentialsとDocker Essentialsの作成者でもあります。PHPコードの作成に取り組んでいないときは、TwilioのPHP記事の優秀な編集者です。彼の連絡先は、msetter[at]twilio.com、Twitter、 GitHubです。