Phar アーカイブの使用法
Phar アーカイブの使用法: 導入
Phar アーカイブは Java の JAR アーカイブと似た概念のものですが、
PHP アプリケーションで使用する際に必要な機能をより柔軟に使用できるよう改良しています。
Phar アーカイブを使用すると、PHP アプリケーションやライブラリを
ひとつのファイルにまとめて配布できるようになります。
Phar アーカイブ形式のアプリケーションは、その他の PHP
アプリケーションとまったく同様に扱えます。
Phar アーカイブ形式のライブラリを使用する方法も、
その他の通常の PHP ライブラリとまったく同じです。
]]>
phar ストリームラッパーは phar 拡張モジュールの要となるものです。
詳細については こちら
で説明します。このストリームラッパーを使用すると、
phar 内の個々のファイルに対して
fopen や opendir
といった標準のファイル操作関数を使用でき、
まるで通常のファイルシステム上にあるのと同じような感覚でアクセスできます。
phar ストリームラッパーは、
ファイルやディレクトリに対する読み書き操作をすべてサポートしています。
]]>
Phar クラスでは、
ファイルへのアクセスや phar アーカイブ作成用により高度な機能も実装しています。
Phar クラスについての説明は
こちら をご覧ください。
getFileName() . "\n";
echo file_get_contents($file->getPathName()) . "\n"; // 内容を表示します
}
if (isset($p['internal/file.php'])) {
var_dump($p['internal/file.php']->getMetadata());
}
// 新しい phar の作成 - php.ini で phar.readonly を 0 にしておく必要があります。
// phar.readonly は、セキュリティ上の理由によってデフォルトで有効になっています。
// 実際の運用サーバーでは、決して Phar を作成する必要はないはずで、
// 単に実行できるだけでよいはずです。
if (Phar::canWrite()) {
$p = new Phar('newphar.tar.phar', 0, 'newphar.tar.phar');
// tar 形式の phar アーカイブを作成し、gzip で圧縮します (.tar.gz)
$p = $p->convertToExecutable(Phar::TAR, Phar::GZ);
// トランザクションの作成 - newphar.phar には、
// stopBuffering() がコールされるまで (一時的なストレージが必要となっても) なにも書き込まれません
$p->startBuffering();
// すべてのファイルを /path/to/project に追加し、プレフィックス "project" で phar に保存します
$p->buildFromIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator('/path/to/project')), '/path/to/');
// 配列形式の API で新しいファイルを追加します
$p['file1.txt'] = 'Information';
$fp = fopen('hugefile.dat', 'rb');
// すべてのデータをストリームからコピーします
$p['data/hugefile.dat'] = $fp;
if (Phar::canCompress(Phar::GZ)) {
$p['data/hugefile.dat']->compress(Phar::GZ);
}
$p['images/wow.jpg'] = file_get_contents('images/wow.jpg');
// ファイルのメタデータには任意の値を保存できます
$p['images/wow.jpg']->setMetadata(array('mime-type' => 'image/jpeg'));
$p['index.php'] = file_get_contents('index.php');
$p->setMetadata(array('bootstrap' => 'index.php'));
// phar アーカイブをディスクに保存します
$p->stopBuffering();
}
} catch (Exception $e) {
echo 'Phar をオープンできません: ', $e;
}
?>
]]>
さらに、phar ファイルの中身の検証を行うこともできます。対称型ハッシュアルゴリズム
(MD5、SHA1、SHA256、そしてもし ext/hash が有効ならさらに SHA512) のいずれか、
あるいは OpenSSL を使用した非対称公開鍵/秘密鍵ペアによる署名のいずれかを使用します。
OpenSSL による署名を使用するには、
まず公開鍵/秘密鍵のペアを作成し、秘密鍵を使用して
Phar::setSignatureAlgorithm で署名を行います。
公開キーによる展開はこのようなコードで行います。
]]>
公開鍵は phar アーカイブと同じ場所、名前でなければなりません。つまり、phar アーカイブの保存先が
/path/to/my.phar の場合は公開鍵を
/path/to/my.phar.pubkey としなければなりません。
そうしないと、OpenSSL 署名の検証ができなくなります。
Phar には 3 つのstaticメソッド
Phar::webPhar、
Phar::mungServer そして Phar::interceptFileFuncs
が追加されました。これは、通常のファイルシステム用あるいはウェブアプリケーション用の
PHP アプリケーションのパッケージを作成する際に重要となります。
Phar::webPhar は、HTTP のコールを phar
アーカイブ内の特定の場所に転送するフロントコントローラを実装します。
Phar::mungServer は
$_SERVER 配列の中身をうまく変更して
アプリケーションでその値を使えるようにします。
Phar::interceptFileFuncs は、
fopen や file_get_contents、opendir
そしてすべての stat 系関数 (file_exists、is_readable など)
のコールを Phar が横取りして、相対パスを phar アーカイブ内の適切な位置に変換するようにします。
たとえば、あの有名な phpMyAdmin を phar アーカイブにすることを考えてみましょう。
必要なのは、こんな単純なスクリプトだけです。あとは、
ユーザー名とパスワードを変更してウェブサーバー上から
phpMyAdmin.phar.tar.php にアクセスするだけで利用できます。
startBuffering();
$a["phpMyAdmin-2.11.3-english/config.inc.php"] = 'setStub('stopBuffering();
?>
]]>
Phar アーカイブの使用法: phar ストリームラッパー
Phar ストリームラッパーは、fopen による読み込みや
書き込み (追記は除く)、unlink、stat、
fstat、fseek、rename
そしてディレクトリに対する opendir、rmdir
や mkdir といった機能に完全に対応しています。
Phar アーカイブ内の各ファイルの圧縮やファイル単位のメタデータの操作も、
ストリーム上で可能です。
array('compress' => Phar::GZ)),
array('metadata' => array('user' => 'cellog')));
file_put_contents('phar://my.phar/somefile.php', 0, $context);
?>
]]>
phar ストリームラッパーは、
リモートファイルを操作することはできません。つまり、INI 設定
allow_url_fopen および
allow_url_include
が無効になっている場合でも使用できます。
ストリーム操作だけで新しい phar アーカイブをゼロから作成することも可能ですが、
そんな場合は Phar クラスの組み込み機能を使用するほうが便利です。
ストリームラッパーが有用なのは、読み込み専用の操作を行う場合です。
Phar アーカイブの使用法: Phar クラスおよび PharData クラス
Phar クラスは Phar アーカイブの読み込みや操作をサポートしています。
また RecursiveDirectoryIterator
クラスを継承しているため、順次処理も可能です。
ArrayAccess インターフェイスをサポートしているので、
Phar アーカイブ内のファイルに対して、
それがまるで連想配列であるかのようにアクセスすることができます。
PharData クラスは Phar
を継承したもので、実行可能でない (データ) tar アーカイブおよび
zip アーカイブなら php.ini で
phar.readonly=1 であっても作成/変更できるようになります。
このクラスでは
PharData::setAlias と PharData::setStub
は使用不可能になっています。というのもエイリアスやスタブというのは
実行可能な phar アーカイブに独特の概念だからです。
注意すべき点は、Phar アーカイブを作成する際には
Phar のコンストラクタに
フルパスを渡さなければならないということです。
相対パスでは初期化に失敗します。
$p が、次のように作成した Phar オブジェクトであるとしましょう。
]]>
空の Phar アーカイブが /path/to/myphar.phar
に作成されます。もし /path/to/myphar.phar
が既に存在する場合は、それを再度オープンします。
リテラル myphar.phar は、エイリアスを表します。
これを用いると、URL で /path/to/myphar.phar
を参照する際に次のようにできます。
]]>
新しく作成した Phar オブジェクト
$p に対して、次のような処理が可能となります。
$a = $p['file.php'] とすると、
phar://myphar.phar/file.php の中身を参照する
PharFileInfo クラスが作成されます。
$p['file.php'] = $v とすると、
myphar.phar の中に新しいファイル
(phar://myphar.phar/file.php)
を作成するか、あるいは同名のファイルを上書きします。
$v には、文字列あるいはファイルポインタのいずれかを指定できます。
ファイルポインタを指定した場合は、その中身全体をもとにして新しいファイルを作成します。
$p->addFromString('file.php', $v) は、
機能的に上と同じであることに注意しましょう。また、ファイルの中身を
$p->addFile('/path/to/file.php', 'file.php')
で追加することもできます。最後に、空のディレクトリを作成するには
$p->addEmptyDir('empty') とします。
isset($p['file.php'])
とすると、phar://myphar.phar/file.php が
myphar.phar の中に存在するかどうかがわかります。
unset($p['file.php']) とすると、
phar://myphar.phar/file.php を
myphar.phar から削除します。
さらに、Phar 固有のメタデータにアクセスするためには
Phar オブジェクトを使用することが唯一の方法となります。そのためには
Phar::getMetadata
を使用します。また、Phar アーカイブの PHP ローダスタブを設定したり取得したりするための唯一の方法が
Phar::getStub および
Phar::setStub です。
また、Phar アーカイブ全体の圧縮を行うには
Phar クラスが必要となります。
Phar オブジェクトの全機能の一覧については、以下で説明します。
PharFileInfo クラスは
SplFileInfo
クラスを継承しており、Phar 内のファイルについての Phar
固有の情報 (圧縮情報やメタデータなど) を扱うためのメソッドが追加されています。