リクエスト送信
クライアントとしてのWebサーバー
Webのアプリケーションでは、外部のAPI等を実行するという場面があります。
例えばユーザーが郵便番号を入力したら、それに該当する住所を自動入力するインターフェイスなどは、住所データベースを持つよりも、例えば日本郵政の提供する住所検索APIを利用する方が便利です。そのような外部APIを利用する場合、当然ブラウザでそのURLを入力すれば、そのレスポンスがブラウザに表示されます。これは、ブラウザがクライアントとしてリクエストを送信し、返ってきたレスポンスを表示するという機能を持っているためです。しかし、今欲しいのはそういうことではなく、PHPのプログラム上でリクエストを送信し、そのレスポンスを文字列として取得することです。
通常、PHPではWebサーバーとしてのプログラムを作成します。これは、どこかの一般ユーザーのブラウザがクライアントということになり、そこから送信されてきたリクエストを処理するのがあなたの構築するWebサーバーであり、そのWebサーバーで動作するPHPという関係です。
今回のリクエスト送信というのはPHPからリクエストを送信するわけなので、あなたのWebサーバーがクライアントということになります。そしてそれを受け取ってレスポンスを返すサーバーは外部のWebサービスを提供しているどこかのWebサーバーです。
つまり、
クライアント(ユーザー) → Webサーバー(あなた) → Webサーバー(外部)
というリクエストの流れになるわけで、今回取り上げるのはこの後半部分というわけです。
このような機能を実現するZend2の機能について見ていきます。
リクエスト送信の基本
Zend2にはHTTPリクエストの送信を行うためのクラスが存在します。
Zend\Http\Clientです。
このクラスを使って、住所検索APIを利用する例を見てみましょう。
利用するAPIは以下です。
http://zipcloud.ibsnet.co.jp/api/search?zipcode=7830060
use Zend\Http\Client; $url = 'http:⁄⁄zipcloud.ibsnet.co.jp/api/search?zipcode=7830060'; $client = new Client($url); $response = $client->send();
これだけのことです。
Zend\Http\Client
setUri
Clientクラスはコンストラクタの第1引数でリクエスト先のURLを指定しますが、後からsetUriメソッドで指定することも可能です。この場合、コンストラクタは引数なしでかまいません。
$client = new Client(); $client->setUri('http:⁄⁄zipcloud.ibsnet.co.jp/api/search?zipcode=7830060'); $response = $client->send();
setParameterGet
送信するGETメソッドのパラメーターを設定します。
例えば、
http:⁄⁄zipcloud.ibsnet.co.jp/api/search?zipcode=7830060
というURLは、URL中に「zipcode=7830060」というGETパラメーターを含んでいますが、これを以下のように明示的にメソッドで別途指定することが可能です。
$client = new Client(); $client->setUri('http:⁄⁄zipcloud.ibsnet.co.jp/api/search'); $client->setParameterGet(array('zipcode' => '7830060')); $response = $client->send();
setParameterPost
POSTメソッドのパラメーターを設定します。
$client = new Client(); $client->setUri('http:⁄⁄www.hoge.net/api'); $client->setParameterPost(array('fuga' => 'xxxxxx'));
setMethod
送信するHTTPメソッドを指定します。デフォルトはGETです。
use Zend\Http\Request; $client = new Client('http:⁄⁄www.hoge.net/api'); $client->setMethod(Request::METHOD_POST); $client->setParameterPost(array('fuga' => 'xxxxxx')); $client->send();
setHeaders
HTTPリクエストヘッダを設定します。
指定できるHTTPリクエストヘッダは非常にたくさん存在するため、全ては挙げませんが、Zend\Http\Header名前空間の中には大部分がクラスとして定義されています。
setHeadersメソッドは連想配列により指定が可能で、ヘッダ名とそれに対する値の組合せで指定します。
ヘッダ名は例えばContentTypeなら"ContentType"がヘッダ名なので、これをそのまま直接指定してもかまいませんが、
Zend\Http\Header\ContentTypeクラスのgetFieldNameメソッドで"ContentType"が返ってくるため、例のようにこれを利用すべきです。
Zend\Http\Header名前空間の下にあるクラスは全てZend\Http\Header\HeaderInterfaceを実装しており、これにより、getFieldNameメソッドが必ず存在する事が保証されています。
use Zend\Http\Header\ContentType; $client = new Client('http:⁄⁄www.hoge.net/api'); // コンテンツタイプにtext/xmlを指定 $contentType = new ContentType(); $client->setHeaders(array( $contentType->getFieldName() => 'text/xml' )); $client->send();
setOptions
リクエストのオプションを設定します。
オプションの指定はsetOptionsで指定する以外に、コンストラクタの第2引数で指定することも可能です。
$client = new Client('http:⁄⁄www.hoge.net/api'); $client->setOptions(array( 'timeout' => 30, 'maxredirects' => 0, )); $client->send(); // コンストラクタでの指定も可能 $client = new Client('http:⁄⁄www.hoge.net/api', array( 'timeout' => 30, 'maxredirects' => 0, )); $client->send();
以下に指定可能なオプションをいくつか紹介します。
- timeout - リクエストのタイムアウト秒数を設定
- keepalive - ApacheのKeepAliveを有効にするか無効にするかを設定
- httpversion - HTTPのバージョンを指定
- maxredirects - リクエスト先で許容するリダイレクトの回数を指定
レスポンスの処理
Zend\Http\Clientクラスのsendメソッドを実行するとリクエストが送信され、レスポンスが得られます。
このsendメソッドの戻り値として得られるのはZend\Http\Responseクラスのインスタンスです。
ここからどのようにしてレスポンス情報を得るのかを見ていきます。
Zend\Http\Clientクラスのsendメソッドにより、リクエストが送信されますが、
そのレスポンスはZend\Http\Responseクラスのインスタンスがsendメソッドの返り値として返ってきます。
$url = 'http:⁄⁄zipcloud.ibsnet.co.jp/api/search?zipcode=7830060'; $client = new Client($url); $response = $client->send(); var_dump(get_class($response)); var_dump($response->getBody());
string(18) "Zend\Http\Response" string(290) "{ "message": null, "results": [ { "address1": "高知県", "address2": "南国市", "address3": "蛍が丘", "kana1": "コウチケン", "kana2": "ナンコクシ", "kana3": "ホタルガオカ", "prefcode": "39", "zipcode": "7830060" } ], "status": 200 }"
例の通り、sendの返り値であるResponseのインスタンスのgetBodyメソッドでレスポンス本体が取得できます。
その他、レスポンス情報をいろいろと取得するメソッドが用意されています。
Zend\Http\Response
getBody
レスポンスボディを取得するにはgetBodyメソッドを実行します。
文字列情報として取得できますので、その形式に応じて例えばJSONやXMLならパースしたりします。
例えばJSONの場合は以下の様な感じです。
use Zend\Json\Json; $url = 'http:⁄⁄zipcloud.ibsnet.co.jp/api/search?zipcode=7830060'; $client = new Client($url); $response = $client->send(); $body = $response->getBody(); $data = Json::decode($body, Json::TYPE_ARRAY); var_dump($data);
array(3) { ["message"]=> NULL ["results"]=> array(1) { [0]=> array(8) { ["address1"]=> string(9) "高知県" ["address2"]=> string(9) "南国市" ["address3"]=> string(9) "蛍が丘" ["kana1"]=> string(15) "コウチケン" ["kana2"]=> string(15) "ナンコクシ" ["kana3"]=> string(21) "ホタルガオカ" ["prefcode"]=> string(2) "39" ["zipcode"]=> string(7) "7830060" } } ["status"]=> int(200) }
getStatusCode
HTTPのレスポンスには必ずステータスコードがついてきます。
成功の場合は200、リクエストURLが存在しなければ404、プログラムエラーなどは500などがよく見るステータスコードです。ブラウザでのリクエスト時にも、404や500はエラーとしてブラウザに表示されますね。
このステータスコードを取得するのがgetStatusCodeです。
$client = new Client($url); // OK $client->setUri('http:⁄⁄zipcloud.ibsnet.co.jp/api/search?zipcode=7830060'); $response = $client->send(); $code = $response->getStatusCode(); var_dump($code); // NOT FOUND $client->setUri('http:⁄⁄zipcloud.ibsnet.co.jp/hogehoge'); $response = $client->send(); $code = $response->getStatusCode(); var_dump($code);
int(200) int(404)
isOk, isNotFound, isForbidden
これら3つは、ステータスコードがそれぞれの意味する物コードであるか否かを調べます。
OKは200、NOT FOUNDは404、Forbiddenは403です。
$client->setUri('http:⁄⁄zipcloud.ibsnet.co.jp/api/search?zipcode=7830060');
$response = $client->send();
var_dump($response->isOk());
var_dump($response->isNotFound());
var_dump($response->isForbidden());
bool(true) bool(false) bool(false)
isInformational, isSuccess, isRedirect, isClientError, isServerError
定義されているステータスコードは全て数えると数十個ありますが、それらは5つの分類に別れます。
100番台が情報、
200番台が成功、
300番台がリダイレクト、
400番台がクライアントエラー、
500番台がサーバーエラー
です。
OKを表す200は成功に分類されますし、
NOT FOUNDを表す404はクライアントエラーに分類されます。
isInformational, isSuccess, isRedirect, isClientError, isServerErrorという5つのメソッドは、ステータスコードがそれぞれの分類であるか否かを調べます。
$client->setUri('http:⁄⁄zipcloud.ibsnet.co.jp/api/search?zipcode=7830060');
$response = $client->send();
var_dump($response->isInformational());
var_dump($response->isSuccess());
var_dump($response->isRedirect());
var_dump($response->isClientError());
var_dump($response->isServerError());
bool(false) bool(true) bool(false) bool(false) bool(false)
getReasonPhrase
ステータスコードとセットで必ずリーズンフレーズというものがくっついてきます。
これはステータスコードの表す意味を人間にわかりやすい英語表現したものです。
例えば200であれば"OK"、404であれば"Not Found"などです。
getReasonPhraseはこのリーズンフレーズを得るメソッドです。
$client->setUri('http:⁄⁄zipcloud.ibsnet.co.jp/api/search?zipcode=7830060');
$response = $client->send();
var_dump($response->getReasonPhrase());
string(2) "OK"
toString
toStringは、レスポンス情報をレスポンスヘッダを含め、そのまま全て生の状態の文字列で取得します。
$client->setUri('http:⁄⁄zipcloud.ibsnet.co.jp/api/search?zipcode=7830060');
$response = $client->send();
var_dump($response->toString());
string(550) "HTTP/1.1 200 OK Content-Type: text/plain; charset=utf-8 Vary: Accept-Encoding Date: Wed, 04 Mar 2015 14:34:25 GMT Server: Google Frontend Cache-Control: private Alternate-Protocol: 80:quic,p=0.08,80:quic,p=0.08 Accept-Ranges: none Connection: close { "message": null, "results": [ { "address1": "高知県", "address2": "南国市", "address3": "蛍が丘", "kana1": "コウチケン", "kana2": "ナンコクシ", "kana3": "ホタルガオカ", "prefcode": "39", "zipcode": "7830060" } ], "status": 200 }
getHeaders
レスポンスのヘッダ情報を取得します。
getHeadersの戻り値はZend\Http\Headersクラスのインスタンスです。
Headersは復数のヘッダ情報を保持するコレクションクラスになっています。
個々のヘッダ情報はHeadersのgetメソッドでヘッダ名を指定することで取得します。
use Zend\Http\Header\ContentType; $contentType = new ContentType(); $client = new Client('http:⁄⁄zipcloud.ibsnet.co.jp/api/search?zipcode=7830060'); $response = $client->send(); $headers = $response->getHeaders(); $contentType = $headers->get($contentType->getFieldName()); var_dump($contentType->getFieldValue());
string(25) "text/plain; charset=utf-8"