Symfony Consoleで学ぶ「CLIツールの入口構造」
〜 bin/console がコマンドを呼ぶまでを読み解く 〜
PHPのOSSを読むとき、「どこが入口なのか分からない」が最大の壁になりがちです。
特に phpstan のように CLIで動くツールは、CLIの入口構造が分かると理解が一気に進みます。
この記事では、Symfony Console(symfony/console)を題材にして、
- CLIツールがどう起動されるか
- コマンドがどう登録されて実行されるか
- OSSを読むときどこを見ればいいか
を整理します。
1. なぜ Symfony Console を読むのが良いのか?
Symfony Console は、PHPのCLIツール実装の「王道」です。
- Laravelの
artisanは Symfony Console ベース - phpstan や php-cs-fixer も同系統の構造
- CLIの設計パターンが綺麗に抽象化されている
つまり Symfony Console を読めるようになると、
✅ Laravelの artisan の内部が読める
✅ phpstan の入口が追える
✅ 自分でCLIツールを作れる
という状態になれます。
2. CLIツールの “入口” はどこ?
結論から言うと、CLIツールの入口はほぼ必ず次のどれかです。
✅ A. bin/ ディレクトリ
例:bin/console / vendor/bin/phpstan など
→ 直接実行されるスクリプトがある
✅ B. composer.json の bin
composer.json に "bin": ["bin/xxxx"] がある
→ vendor/bin/xxxx が作られる
✅ C. READMEの実行例
READMEに php bin/console ... と書いてある
→ そこから入口を逆算できる
3. OSSを読む最初の一手:composer.json を見る
Symfony Console を読むときも、最初に見るべきは composer.json です。
✅ ここで見たいポイント(OSS読解の基本)
- autoload(src がどこに紐づくか)
- dependencies(何に依存しているか)
- require PHP version(対応範囲)
- bin があるかどうか(ある場合はCLI入口)
Symfony Console 自体は「ライブラリ」であって、単体で bin/console は持ちません。
ですが、SymfonyプロジェクトやLaravelなどが Console を使って bin/console を作る。
なので Console の理解では次が重要になります:
「bin/console は自分のアプリ側にある」
「Console は CLIの仕組みを提供する側」
4. CLIツールは何をしているのか(全体像)
CLIツールの処理は だいたい4ステップにまとまります。
✅ CLIが動くときの4ステップ
-
入口スクリプトが起動する
-
bin/consoleが実行される
-
-
Application(コンテナ)が作られる
-
new Application()など
-
-
Command が登録される
$app->add(new FooCommand())- もしくは自動登録(DIなど)
-
ユーザー入力に応じて Command が選ばれて実行される
-
$app->run()の中で - 入力解析 → コマンド選択 → execute()
-
つまり CLIを読むときの一番の目的は:
「入口 → Application → Command登録 → 実行」
この流れがどこで起きているかを見つけること。
5. Symfony Consoleで “役者” を押さえる
Symfony Console の理解を一気に進めるには、重要クラスを3つ覚えるだけでOKです。
✅ 重要クラス3つ
① Symfony\Component\Console\Application
- CLIツールの “本体”
- コマンド一覧を保持する
- 入力からコマンドを選んで実行する
② Symfony\Component\Console\Command\Command
- 各コマンドのベースクラス
-
configure()とexecute()が重要
③ Symfony\Component\Console\Input / Output
- 入力(引数・オプション)と出力(標準出力)の抽象化
6. 実際に「入口の流れ」を追うときの読み方
ここからが、OSS読解の実践パートです。
✅ 手順:まず “呼ばれている順” に追う
CLIの入口側(bin/console)にはだいたいこういう流れがあります:
- autoload 読み込み
- Application生成
- コマンド登録
- run()
この「見慣れた形」を探すだけで良い。
✅ 入口スクリプトで探すべきキーワード
require __DIR__ . '/../vendor/autoload.php'new Application(...)$application->add(...)$application->run()
✅ $application->run() の中で何が起きる?
OSSを読むときは run() の中身を全部理解しようとしないで、
- 入力がパースされる場所
- コマンドを選ぶ場所
- コマンドを実行する場所
だけ追えばOK。
ここで「CLIツールの骨格」が掴めます。
7. Commandの読み方:configure → execute が仕様
コマンドクラスを読みに行くと、
-
configure()が “使い方の定義” -
execute()が “処理本体”
になっています。
✅ configure() が何をしているか
- コマンド名
- 説明
- 引数(arguments)
- オプション(options)
つまり configure() は CLIの仕様書です。
✅ execute() が何をしているか
- 実際のビジネスロジック
- サービス呼び出し
- 入出力の処理
8. Symfony Consoleを読むことで得られる「転用可能な知識」
Symfony Consoleの構造理解は、そのまま以下に転用できます。
✅ Laravel artisan の読解
- artisan は結局
ApplicationとCommandの上に成り立ってる -
Illuminate\Console\Applicationは Symfony Console を拡張している
✅ phpstan の入口理解
- phpstanは
vendor/bin/phpstanを起点に - Console の Application と同じ思想で動く
- コマンドの登録と実行のパイプラインが似ている
✅ 自作CLIツール設計
- Commandに責務を閉じ込める
- Applicationは “選択と実行” のみに集中
- 入出力は抽象化する
9. OSS読解のコツ(初心者がハマるポイント回避)
❌ すべての内部クラスを理解しようとしない
Consoleは内部で色々やってますが、
- アプリとして使う側が触るのは
ApplicationとCommandが中心 - そこを起点に読むと迷わない
✅ tests も “コマンドの仕様書”
Symfony Consoleにも tests があり、
「入力したときどういう結果になるべきか」が書かれています。
OSSは READMEより testsが真実なので、
慣れてきたら testsから読むのもおすすめ。
まとめ:Symfony Consoleで押さえるべき最短ルート
✅ 入口スクリプト(bin/console / vendor/bin/xxx)を見る
✅ Application の生成・run() を見る
✅ Command の configure/execute を見る
✅ tests で挙動を確認する
Discussion