Phar の仕組みを利用した PEAR モジュールのもっと便利な使い方
別にPEARに限った話ではないんですが,ここからが PHP の本気です!!
ってことで,tar などで圧縮されたファイルをそのまま読むことが出来るようになったので,その使い方をちょっと紹介.
Phar
PHP 5.3 から標準搭載された Phar (PHP Archive *1 ) の仕組み(の一部)を使うと,tar や zip で固められたバイナリデータの中身を直接ファイルとして読み込むことができます.phar:// ストリートがストリームラッパーに登録されているので,それを利用して require などをするだけです.
で,これを利用して PEAR ライブラリなどをさらに簡単に利用できるようにしてあげられるよねーと思ったので,利用してみました.
Phar ってなに
その前に Phar ってなにって話をしたいとおもったんですけど,面倒なのでぐぐればいいと思いましたので省略.phar 形式のファイルは,zlib で圧縮されたデータ *2+スタブ(そのデータを扱うためのプログラム)だと思ってもらえれば大丈夫です.
で,今回は特にその Phar 形式のファイルは使いません.
Phar ストリームラッパーのおかげで,tgz/zip で固められたデータの中身を解凍せずにそのままファイルとして読み込めるようになったので,それを利用してライブラリを使おうって話です.
とりあえずなにか適当に PEAR のファイルを用意する
とりあえず,こっから HTTP_Request2-0.5.1.tgz をダウンロードしてきます.
そうすると,今,ディレクトリは,
% ls HTTP_Request2-0.5.1.tgz load_library.php
みたいなかんじになっている状態です.
PharData で中身を確認
あとは普段どおり + phar:// ストリームをつかいます.
と,その前に,PharData クラスを使って,中身がどういう構成かを確認したいとおもいます.
<?php foreach (new RecursiveIteratorIterator(new PharData('HTTP_Request2-0.5.1.tgz')) as $f) { echo $f, PHP_EOL; }
そうすると,
phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/Request2/Adapter/Curl.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/Request2/Adapter/Mock.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/Request2/Adapter/Socket.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/Request2/Adapter.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/Request2/Exception.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/Request2/MultipartBody.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/Request2/Observer/Log.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/Request2/Response.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/Request2.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/docs/examples/upload-rapidshare.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/AllTests.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/ObserverTest.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/Request2/Adapter/AllTests.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/Request2/Adapter/MockTest.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/Request2/AllTests.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/Request2/MultipartBodyTest.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/Request2/ResponseTest.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/Request2Test.php phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/_files/bug_15305 phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/_files/empty.gif phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/_files/plaintext.txt phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/_files/response_cookies phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/_files/response_deflate phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/_files/response_gzip phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/_files/response_gzip_broken phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/tests/_files/response_headers phar:///home/sotarok/git/sandbox/php/phar_pear/HTTP_Request2-0.5.1.tgz/package.xml
のように,中身を見ることができます.RecursiveIterator を実装しているので RecursiveIteratorIterator が役に立ちますね.(参考: モダンPHP勉強会を開催しました & 資料 - 肉とご飯と甘いもの @ sotarok)
phar:// ストリームでファイルの中身を require
目的のファイルをrequireして,あとはいつもどおりに使うだけです.先程出力をされたものは phar:// ストリーム+ファイルの絶対パスになっていますが,もちろん相対パスでも指定可能です.HTTP_Request2-0.5.1.tgz に続けて普通にファイルにアクセスするようにパスを指定します.
<?php require_once 'phar://HTTP_Request2-0.5.1.tgz/HTTP_Request2-0.5.1/Request2.php'; $r = new HTTP_Request2('http://nequal.jp/'); $response = $r->send(); echo $response->getBody();
Request2.php 内でほかのファイルを require しているはずですが,このあたりは相対パスでよしなにやっているのでしょうか.(未調査)
依存ライブラリがあったときに困りそうだなあ.
まとめ
pharストリームを使えば,圧縮されたファイルでも,解凍せずに中身のPHPファイルを直接ロードして使うことができるます.file_get_contents などもできますし,画像データなども圧縮しておいたものをそのまま使うこともできます.
今回は,PharData を使って中身を確認してからファイルをロードしましたが,このあたりは自動化できるはずですね.例えば,PEAR 形式に関して言えば, package.xml を探し出して,その中身をチェックし,例えば,Loader::load('HTTP/Request2.php'); のようにしたら自動でその中身を読み込んできてくれるものを作ったり.
XOOPS や WordPress のような CMSで,ユーザにプラグインをインストールさせる際,pear コマンドを使わずに,tgz をアップロードするだけでライブラリを使うことができる,そんな仕組みを実現することもできます.
このあたりに対応したフレームワークとかもそのうち出てくるんじゃないでしょうかねー.
Phar データのスタブを使えばもっと色々できますし,Phar はまだまだ活躍の幅を広げられそうです.