野暮用でPHPで書いたツールをPharにすることになりました。
pharというのはcomposer.pharとかのあれです。アプリを構成する複数のファイルを一つの実行可能なファイル(もちろん別途PHPを導入しておく必要はあります)にまとめることができるやつです。正確にはそれだけのものではありませんが、2016年においてそれ以外の用途も特に思いつかないのでそれでいいと思います(投げやり
で、PHP: Phar - Manual を読んでみたんですがまったく意味がわかりません。スタブってなんだよ!__HALT_COMPILER();
とかなにそれ怖い……
でもまあ、こういう面倒なことにはなんらかツールが用意されているものだと探してみたらありました。Boxです。これを使えば簡単にPharを作成することができます。
PHP: Phar - Manual が理解できなくても大丈夫。そう、Boxならね。
まずはBoxをインストールしましょう。
$ curl -LSs https://box-project.github.io/box2/installer.php | php
成功するとカレントディレクトリにbox.phar
というファイルが生成されるので、/usr/local/bin/box
にでもコピーして、パーミッションを755に変更します。これでbox
コマンドが使えるようになりました。
さて、Phar化する対象のプロジェクトですが今どきだとだいたいこんな構成になっているかと思います。
.
├── composer.json
├── composer.lock
├── main.php
├── phpunit.xml
├── src/
├── tests/
└── vendor/
-
main.php
がコマンドのエントリポイント -
src
にPSR0/PSR4でロードするphpファイル -
tests
にテスト関係のファイル -
vendor
にcomposerで導入したパッケージ
main.php
の内容としてはこんな感じ。
<?php
require_once __DIR__ . '/vendor/autoload.php';
$app = new Example\ConsoleApplication();
$app->run();
典型的ですね。
これをPhar化してみましょう。
まずはプロジェクトのトップディレクトリにbox.json
を用意します。Boxのデフォルトのコンフィグファイルです。内容はこのようします。
{
"directories": ["src", "vendor"],
"main": "main.php",
"output": "example.phar",
"chmod": "0755",
"stub": true
}
-
directories
に指定したディレクトリ以下のphpファイルがアーカイブの対象になります -
main
に指定したphpファイルがpharを実行したときに実行されます -
output
は生成するpharファイル名です - 他はおまじない
とにかく、directories
にアプリを動作させるのに必要なphpファイルの入ったディレクトリ、main
にエントリポイントとなるphpファイルを指定すればOKです。こんな大雑把な設定では無駄なファイル(例えば各パッケージのテスト関連のファイル)も沢山入ってしまうかもしれませんが動けばいいのだ!もちろん設定次第ではアーカイブ対象のファイルを事細かに指定することもできるので、気になる人はbox help build
を熟読しましょう。
box.json
が用意できたらbox build
を実行します。
$ box build
Building...
これでexample.phar
が生成されます。あとは、これをPATHの通ったディレクトリにコピーするなり、配布するなりお好きなように。
補足
PHPUnitなどrequire-dev
で入るパッケージはアプリの動作には必要ないので、pharの容量を削減するためにはできれば含めたくないところかもしれません。そんなときは、box build
を実行する前にcomposer install --no-dev
でパッケージをインストールし直しましょう。doctrine-migrationsのビルドスクリプトが参考になるかもしれません。box.json
で個別にPHPUnitのパッケージをexcludeすることもできるかもしれませんがこちらのほうが簡単でしょう。