pecl_http の隠し機能?

今回は HttpRequest クラスのドキュメント化されていない (っぽい) 機能を紹介します。
なんと、サブクラスのメソッドとして onfinish が定義されている場合、リクエスト終了時に自動でコールされるのです。
onfinish メソッドは引数としてリクエストが成功したか (valid な HTTP Response が返ってきたか) を boolean として受け取ります。


利用例としてはこのようなクラスが考えられます。

<?php
class UrlRetrieve extends HttpRequest
{
    private $savepath;

    public function __construct($url, $savepath,
                                $method = HttpRequest::METH_GET,
                                $options = array())
    {
        parent::__construct($url, $method, $options);
        $this->savepath = $savepath;
    }

    public function onfinish($success)
    {
        if ($success && $this->getResponseCode() == 200) {
            file_put_contents($this->savepath, $this->getResponseBody());
        } elseif ($success) {
            // 200 以外のレスポンスが返ってきたときの処理
        } else {
            // HTTP レスポンスが返ってこなかったときの処理
        }
    }
}

このクラスを使うと、ファイルのダウンロードと保存が簡潔に行えます。

<?php
require_once 'UrlRetrieve.php';
try {
    $req = new UrlRetrieve('http://example.com', 'example.html');
    $req->send();
} catch (HttpException $e) {
    // エラー処理
}

これだけなら普通に書いても大して手間は変わらないように思えますが、このクラスの最大のメリットは HttpRequest を継承しており、HttpRequestPool と組み合わせて使えることです。
つまり、複数のリクエストの処理を並列で行えるわけですね。サンプルを こちら に置いておきましたので、興味がある方は UrlRetrieve_seq.php と UrlRetrieve_pool.php の実行時間を比較してみてください。


他にも HttpRequest を継承したクラスで onprogress メソッドが定義されていて、かつ onprogress オプションが指定されていない場合、内部的に array($this, 'onprogress') が onprogress オプションに設定され、実行中に呼ばれるようなのですが、こちらの挙動については調べていません。


ちなみに現在の pecl_http/http_request_pool_api.c では "not implemented; use HttpRequest callbacks" となっていますが、将来は HttpRequestPool でもユーザ定義イベントハンドラがサポートされるかもしれません。