Phar ファイルと Phar フォーマットと、「スタブコード」から呼ばれるエントリポイントについて

Phar ファイルと Phar 形式

*.phar ファイルは “Phar file” と呼ばれる、PHP で複数のファイルをアーカイブして配布 and/or 実行する形式のファイル(アーカイブファイル)のこと。

Phar ファイルの形式としては 3 種類あり、Zip フォーマット、Tar フォーマットと、ネイティブで専用の Phar フォーマットとである(「Phar ファイル」と「Phar フォーマット」の違いに注意)。zip フォーマットと tar フォーマットはそのまま zip や tar のファイルで、メタ情報はアーカイブファイルのルートの .phar/ に格納される。phar フォーマットではメタ情報はアーカイブコンテンツとは別の領域に格納される。

PHP コード内からであれば、ファイルシステム上のファイルへのアクセスのようにだいたい透過的にアクセスすることができるようになっている。

Phar フォーマット

「phar ファイル形式は スタブ/マニフェスト/コンテンツ/シグネチャ で構成されており」 // PHP: Phar ファイルフォーマット - Manual

この「スタブ」は PHP コードであり、Phar ファイルからプログラムを起動する際に用いられる。「スタブ」という用語的にはやや変な感じもするんですが、「スタブ」の語は「全体から、本質の部分を欠くか消費するかして残る小片」の意味があるので、「Phar ファイルから、本質部分である PHP コードの集合を除いた部分の、単なるブート用コード」の意味で「スタブ」と呼称しているものと思われる。

スタブコードを表示するには、 phar(1) コマンドを用いて以下のようにする。

$ phar stub-get -f composer.phar
#!/usr/bin/env php
<?php

// ... 中略 ...

Phar::mapPhar('composer.phar');
require 'phar://composer.phar/bin/composer';

__HALT_COMPILER(); ?>

Phar::mapPhar では、この Phar ファイルを第一引数で指定した Phar 名のエイリアスにマップする。正確に言うと、 __HALT_COMPILER() を呼んでいる Phar ファイルの __HALT_COMPILER(); よりも後ろの部分(PHP コード中からは __COMPILER_HALT_OFFSET__ で参照できるオフセット位置以降の内容)を Phar ライブラリを使ってアクセスできるようにマップする。

上の例であれば、

  1. 本体( __HALT_COMPILER() 以降のファイルの内容)を composer.phar の名前で Phar しとてマップして( mapPhar
  2. エントリポイントからを実行して( require
  3. おしまい( __HALT_COMPILER() )となる

「マニフェスト」は「積荷の目録」であり、「コンテンツ」に載っているファイル群の一覧である。そして「コンテンツ」はデータそのものが格納される領域。

そして require 'phar://composer.phar/bin/composer' しているわけだから、これがエントリポイントになる。

このローダコードを自分で書いて Phar ライブラリなり phar(1) コマンドなりでセットしても良いのですが、簡単に作ってくれる用のツールがある。 // Box by box-project

コマンド

Phar フォーマットか Tar フォーマットの Phar ファイルかとか考えずに、 phar(1) コマンドや Phar ライブラリで統一的に扱える。

ファイル一覧。

phar tree -f /usr/local/Cellar/composer/1.5.2/libexec/composer.phar

スタブコード表示。

phar stub-get -f /usr/local/Cellar/composer/1.5.2/libexec/