PHP マニュアル
前のページ |  | 次のページ

# CXXI. Phar アーカイブストリームおよびクラス

# 導入

phar 拡張モジュールは、 `phar` ストリームラッパーおよび Phar クラスを提供し、 PHP アーカイブ (phar) ファイルを操作することができます。 Phar クラスを使用すると、phar ファイルの作成や展開、 そしてその中身を順に処理することなどができます。

PHP アーカイブファイル (Phar) は複数のファイルをまとめたもので、 外部からその中のファイルを透過的に実行することができます。 Java の jar アーカイブファイルと似たものです。 phar アーカイブを使用すると、 PHP アプリケーションをひとつのファイルにまとめて配布できるようになります。 このファイルは、変更したり展開したりすることなくそのまま外部から実行できます。 phar アーカイブは、tar や zip のアーカイブと同様に、 ファイルを保存するために使用することもできます。 Phar は圧縮もサポートしています。 zlib 拡張モジュールが存在する場合には gzip を、そして bz2 拡張モジュールが存在する場合には bzip2 を使用します。 さらに、SPL 拡張モジュールが存在する場合には、 順次処理やその他の機能が使用可能となります。 md5 や sha1 による Phar の署名の検証は、 hash 拡張モジュールが存在する場合にネイティブでサポートされます。

Phar アーカイブのネイティブな実装は PEAR パッケージ PHP_Archive であり、この拡張モジュールの実装はこれと非常によく似ています。k, and

# 要件

Phar を使用するには PHP 5.2.1 以降が必要です。また、 Phar ファイルの中身に対して配列形式でアクセスしたり順に処理したりするには SPL 拡張モジュールが PHP に組み込まれている必要があります。 `phar` ストリームを使用するには、 これは不要です。

オプションとして、zlib 拡張モジュールおよび bzip2 拡張モジュールを有効にしておくと、 圧縮された phar をサポートすることができます。 さらに、hash 拡張モジュールを使用すると、 phar ファイルへの署名や署名の検証機能を組み込めます。

# インストール手順

Windows 用のバイナリは http://snaps.php.net/ にあります。インストールするには、php_phar.dll をダウンロードして、php.ini の `extension_dir` ディレクティブで指定されたフォルダに配置します。 その後、php.ini に `extension=php_phar.dll` を追加してこれを有効にし、ウェブサーバを再起動します。

    extension_dir=c:/php5/exts/
    extension=php_phar.dll

Linux、BSD その他 *nix 系 の場合は、次の手順でコンパイルします。

- 次の手順か、

  - `pecl install phar` で、PECL/phar のインストーラを実行します。

  - `phar.so` を、ビルド時に表示されたディレクトリから php.ini の `extension_dir` ディレクトリにコピーします。

  - `extension=phar.so` を php.ini に追加します。

  あるいはこちらの手順を実行します。

  - 次のようにして、php.ini へのパスを設定します。

    `pecl config-set php_ini /path/to/php.ini`

  - `pecl install phar` で、PECL/phar のインストーラを実行します。

- ウェブサーバを再起動し、php.ini の設定を読み込ませます。

> 開発バージョン: 現在は、PECL/phar の `安定版` はまだありません。 `アルファ版` の PECL/phar をインストールするには `pecl install phar-`alpha を実行します。

> PEAR コマンドを使用しない PECL/phar のコンパイル: `pecl install phar` を使用すると、 PECL/phar を自動的にダウンロードし、インストールします。しかし、 tar ボールを PECL からダウンロードすることもできます。tar ボールを展開したルートディレクトリで `phpize && ./configure --enable-phar && make` を実行すると `phar.so` が出来上がります。 ビルドしたものを、上のようにしてインストールします。

この PECL 拡張モジュールをインストールする方法は、 マニュアルの PECL 拡張モジュールのインストール という章にあります。 新規リリース・ダウンロード・ソースファイル・管理者情報・CHANGELOG といった関連する情報については、次の場所にあります。 http://pecl.php.net/package/phar.

# 実行時設定

`php.ini` の設定により動作が変化します。

表 1. ファイルシステムおよびストリームの設定オプション

名前 | デフォルト | 変更の可否 | 変更履歴
--- | --- | --- | ---
phar.readonly | "1" | PHP_INI_SYSTEM | バージョン 1.0.0 以降で使用可能
phar.require_hash | "0" | PHP_INI_SYSTEM では有効化/無効化、PHP_INI_ALL では有効化のみ | バージョン 1.0.0 以降で使用可能

以下に設定ディレクティブに関する 簡単な説明を示します。

`phar.readonly` boolean

  このオプションを使用すると、`phar` ストリームや Phar オブジェクトによる Phar アーカイブの作成や変更ができなくなります。 この設定は、実運用環境では常に有効にしておくべきです。 phar 拡張モジュールのこの機能は、 サーバ上に他のセキュリティ上の脆弱性があった場合に php ベースのウィルスを直接作成されてしまうことにつながります。

  > 注意: この設定は、セキュリティ上の理由により php.ini でしか設定できません。

`phar.require_hash` boolean

  このオプションを使用すると、署名つき (現在サポートしているのは md5 および sha1) の Phar アーカイブのみをオープンするようになります。 署名を含まない Phar アーカイブの処理はできません。

  > 注意: このオプションを無効にできるのは、システムレベルに限定されます。 しかし、スクリプト内で ini_set() を使用すると、システム設定にかかわらず有効にできます。

# リソース型

Phar 拡張モジュールで使用するリソースは `phar` ストリームで、これにより、phar 内のファイルへの透過的なアクセスが可能となります。 Phar ファイルのフォーマットについては ここ で説明されています。

リソース型は定義されていません。

# 定義済みクラス

Phar
PharFileInfo
PharException

# Phar アーカイブの使用法: 導入

Phar アーカイブは Java の JAR アーカイブと似た概念のものですが、 PHP アプリケーションで使用する際に必要な機能をより柔軟に使用できるよう改良しています。 Phar アーカイブを使用すると、PHP アプリケーションやライブラリを ひとつのファイルにまとめて配布できるようになります。 Java における JAR アーカイブの実装とは異なり、 PHP の Phar アーカイブを処理したり実行したりするには外部のツールは不要です。 Phar アーカイブ形式のアプリケーションは、その他の PHP アプリケーションとまったく同様に扱えます。

    php coolapplication.phar

Phar アーカイブ形式のライブラリを使用する方法も、 その他の通常の PHP ライブラリとまったく同じです。

`<?php include 'coollibrary.phar'; ?>`

Phar アーカイブを非常に便利なものとしている機能が `phar` ストリームラッパーです。 詳細については こちら で説明します。このストリームラッパーを使用すると、 phar 内の個々のファイルに対して、 まるで通常のファイルシステム上にあるのと同じような感覚でアクセスできます。 `phar` ストリームラッパーは、 ファイルに対する読み書きや、ディレクトリに対する opendir() をすべてサポートしています。

`<?php include 'phar://coollibrary.phar/internal/file.php'; header('Content-type: image/jpeg'); // phar にアクセスするには、フルパスあるいはエイリアスを使用します echo file_get_contents('phar:///fullpath/to/coollibrary.phar/images/wow.jpg'); ?>`

Phar 拡張モジュールで提供されているもうひとつの機能が Phar クラスです。 これにより、Phar アーカイブ内のファイルに対して まるでそれが連想配列であるかのようにアクセスできるようになります。 またその他の機能も用意されています。Phar クラスについての説明は こちら をご覧ください。

`<?php
try {
// 既存の phar をオープンします
$p = new Phar('coollibrary.phar');
foreach ($p as $file) {
// $file は PharFileInfo クラスで、これは SplFileInfo を継承しています
echo $file->getFileName() . "\n";
echo $file . "\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(dirname(__FILE__) . '/newphar.phar', 0, 'newphar.phar');
// トランザクションを作成します - commit() がコールされるまで、ディスクには何も書き込まれません
$p->begin();
// 新しいファイルを追加し、その内容を設定します
$p['file1.txt'] = 'Information';
$fp = fopen('hugefile.dat', 'rb');
// ストリームからコピーします
$p['data/hugefile.dat'] = $fp;
if (Phar::canCompress()) {
$p['data/hugefile.dat']->setCompressedGZ();
}
$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->commit('<?php
$p = new Phar(__FILE__);
$m = $p->getMetaData();
require "phar://" . __FILE__ . "/" . $m["bootstrap"];
__HALT_COMPILER();');
}
} catch (BadMethodCallException $e) {
echo 'Phar をオープンできません: ', $e;
}
?>`

# Phar アーカイブの使用法: phar ストリームラッパー

Phar ストリームラッパーは、fopen() による読み込みや 書き込みそして追記、unlink()、stat()、 fstat()、fseek()、rename() そしてディレクトリに対する opendir() といった機能に完全に対応しています。 Phar ストリームラッパーはディレクトリの作成や削除には対応していません。 ファイルは単なるファイルとしてしか格納されず、 ディレクトリを抽象化した概念は存在しないからです。

Phar アーカイブ内の各ファイルの圧縮やファイル単位のメタデータの操作も、 ストリーム上で可能です。

`<?php $context = stream_context_create(array('phar' => array('compression' => Phar::GZ)), array('metadata' => array('user' => 'cellog'))); file_put_contents('phar://my.phar/somefile.php', 0, $context); ?>`

`phar` ストリームラッパーは、 リモートファイルを操作することはできません。つまり、INI 設定 allow_url_fopen が無効になっている場合でも使用できます。

ストリーム操作だけで新しい phar アーカイブをゼロから作成することも可能ですが、 そんな場合は Phar クラスの組み込み機能を使用するほうが便利です。 ストリームラッパーが有用なのは、読み込み操作を行う場合です。

# Phar アーカイブの使用法: Phar クラス

Phar クラスは Phar アーカイブの読み込みや操作をサポートしています。 また RecursiveDirectoryIterator クラスを継承しているため、順次処理も可能です。 ArrayAccess インターフェイスをサポートしているので、 Phar アーカイブ内のファイルに対して、 それがまるで連想配列であるかのようにアクセスすることができます。

`$p` が、次のように作成した Phar オブジェクトであるとしましょう。

`<?php $p = new Phar('myphar.phar'); ?>`

これに対して、次のような処理が可能となります。

- `$a = $p['file.php']` とすると、 `phar://myphar.phar/file.php` の中身を参照する PharFileInfo クラスが作成されます。

- `$p['file.php'] = $v` とすると、 `myphar.phar` の中に新しいファイル (`phar://myphar.phar/file.php`) を作成するか、あるいは同名のファイルを上書きします。 `$v` には、文字列あるいはファイルポインタのいずれかを指定できます。 ファイルポインタを指定した場合は、その中身全体をもとにして新しいファイルを作成します。

- `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 固有の情報 (圧縮情報やメタデータなど) を扱うためのメソッドが追加されています。

# Phar ファイルフォーマット

Phar ファイルは、三つあるいは四つの部分から構成されています。

1. スタブ

2. 内容を説明するマニフェスト

3. ファイルの内容

4. [オプション] Phar の整合性を検証するためのシグネチャ

# Phar ファイルのスタブ

Phar のスタブは、単純な PHP ファイルです。必要最小限のスタブは、次のようになります。

`<?php __HALT_COMPILER();`

スタブには、少なくとも `__HALT_COMPILER();` トークンが必要です。 典型的なスタブは、次のように読み込み機能を含んでいます。

`<?php Phar::mapPhar(); include 'phar://myphar.phar/index.php'; __HALT_COMPILER();`

Phar スタブの内容には特に制限はありません。唯一の制約は、最後が `__HALT_COMPILER();` でなければならないということです。 PHP の終了タグ `?>` は含めても含めなくてもかまいません。 しかし、`;` と終了タグ `?>` の間にはひとつ以上の空白を含めてはいけません。 もしそうしてしまうと、phar 拡張モジュールはその Phar アーカイブを処理できなくなります。

# Phar マニフェストの書式

Phar マニフェストは高度に最適化された書式で、 ファイル単位で圧縮やパーミッションの情報を指定することができ、 さらにユーザやグループなど、独自に定義したメタデータも含めることができます。 1 バイトをこえる大きさの値はリトルエンディアン形式のバイト順で保存されます。 ただし API バージョンだけは例外です。これは 3 ニブルのデータですが、 歴史的な理由によりビッグエンディアン形式のバイト順で保存されます。

未使用のフラグはすべて将来の使用に備えて予約されています。 したがって、独自の情報を保存するためにそれを使用してはいけません。 特定のファイルについて独自の情報を保存するには、 ファイル単位のメタデータ機能を使用します。

Phar アーカイブマニフェストの基本的なファイルフォーマットは、次のようになります。

表 2. グローバル Phar マニフェスト書式

バイト数 | 説明
--- | ---
4 バイト | マニフェスト全体のバイト長 (最大 1 MB)。
4 バイト | Phar 内のファイル数。
2 バイト | Phar マニフェストの API バージョン (現在は 0.9.0)。
4 バイト | グローバルな Phar ビットマップフラグ。
4 バイト | Phar のエイリアスの長さ。
?? | Phar のエイリアス (先ほどの長さに基づきます)。
4 バイト | Phar のメタデータの長さ (存在しない場合は `0`)。
?? | シリアライズ化された Phar メタデータ。serialize() 形式で格納される。
最低でも 24 * エントリ数ぶんのバイト | 各ファイルのエントリ

# グローバルな Phar ビットマップフラグ

これが、Phar 拡張モジュールが現在 Phar フラットビットマップとして認識するフラグです。

表 3. 認識するビットマップ値

値 | 説明
--- | ---
`0x00010000` | 設定されている場合、この Phar には検証用シグネチャが含まれます。
`0x00001000` | 設定されている場合、この Phar には zlib 圧縮されたファイルが少なくともひとつ含まれます。
`0x00002000` | 設定されている場合、この Phar には bzip 圧縮されたファイルが少なくともひとつ含まれます。

# Phar マニフェストのファイルエントリの定義

マニフェスト内の各ファイルについて、次のような情報が含まれます。

表 4. Phar マニフェストのファイルエントリ

バイト数 | 説明
--- | ---
4 バイト | ファイル名の長さを表すバイト数。
?? | ファイル名 (先ほど指定した長さになります)。
4 バイト | 圧縮前のファイルサイズを表すバイト数。
4 バイト | ファイルの Unix タイムスタンプ。
4 バイト | 圧縮後のファイルサイズを表すバイト数。
4 バイト | 圧縮前のファイルの CRC32 チェックサム。
4 バイト | ファイル固有のビットマップフラグ。
4 バイト | シリアライズされたファイルのメタデータの長さ (存在しない場合は `0`)。
?? | シリアライズされたファイルのメタデータ。serialize() の形式で格納される。

ファイル固有のビットマップ値として認識される値は次のとおりです。

表 5. 認識されるビットマップ値

値 | 説明
--- | ---
`0x000001FF` | これらのビットは、ファイルの特定のパーミッションを定義するために予約されています。 このパーミッションは fstat() で用いられ、 ファイルを展開する際に特定のパーミッションを指定することができます。
`0x00001000` | 設定されている場合、この Phar には zlib 圧縮されたファイルが少なくともひとつ含まれます。
`0x00002000` | 設定されている場合、この Phar には bzip 圧縮されたファイルが少なくともひとつ含まれます。

# Phar のシグネチャの書式

シグネチャを含む Phar は、常にシグネチャを保持しています。

表 6. シグネチャのフォーマット

バイト長 | 説明
--- | ---
16 あるいは 20 バイト | 実際のシグネチャ。SHA1 の場合は 20 バイト、 MD5 の場合は 16 バイトとなります。
4 バイト | シグネチャのフラグ。`0x0001` は MD5 シグネチャ、そして `0x0002` は SHA1 シグネチャを表します。
4 バイト | "GBMB" という固定値で、 シグネチャが存在することを表します。

前のページ | ホーム | 次のページ
PDOStatement->setFetchMode() | 上に戻る | Phar::apiVersion