Composer bin スクリプトの作り方

composer をインストールすると、パッケージに含まれる CLI ベースの補助ツールのシンボリックリンクが、自動的に vendor/bin に作られます。
この補助ツールを自分で作る方法について、いろいろと罠にハマったので記録しておきます。

composer.json の bin プロパティに補助ツールのパスを記述します。パスはプロジェクトルートからの相対パスとします。

composer.json
{
  "bin": [
    "path/to/bin",
    "path/to/another",
    ...
  ]
}
  • composer に記述した補助ツールは呼び出しのための bootstrap とし、メイン処理は別ファイルに記述.
  • bootstrap の中では、autoloader の呼び出し、メイン処理の呼び出しのみを記述した方が良い.
  • autoloader の呼び出しは、自パッケージがどこから呼ばれる可能性があるかを意識し、複数の階層から呼ばれる構造にしておく.
  • メイン処理の呼び出しは、既に autoloader を呼み込み済みであるため、クラスを直接呼出し可能.
#!/usr/bin/env php
<?php
$autoloaders = [
    __DIR__ . '/../vendor/autoload.php', // 自プロジェクトからの呼び出し
    __DIR__ . '/../../../../vendor/autoload.php' // composer インストールされた先からの呼び出し
];
 
foreach ($autoloaders as $file) {
    if (file_exists($file)) {
        define('AUTOLOADER_PATH', $file);
        break;
    }
}
unset($file);
require AUTOLOADER_PATH;
 
// Call Main Script
Some\Cli\Application::main();

autoloader と同様、コマンドの引数にパスを渡すような場合、実ファイルのパスをベースに解決しようとすると、自身の存在するパスが変化するため、実装が難しい。
このため、getcwd() という関数を使用することでパスの解決を行う。

Phinx では Symfony\Component\Config\FileLocator というパッケージを使って設定ファイルのパスを解決をしている。

https://github.com/cakephp/phinx/blob/master/src/Phinx/Console/Command/AbstractCommand.php
https://github.com/symfony/config/blob/5.3/FileLocator.php

なお、vendor/bin にはシンボリックリンクが作られるが、シンボリックリンクから実行しても、実行した場所のディレクトリ(シンボリックリンクの親ディレクトリ)を得られるため、気にせず実装できる。

  • devops/php/composer_bin.txt
  • 最終更新: 2021/10/19 21:33
  • by admin