Symfony2のコマンド(タスク)システム
symfony 1.xでシステムを開発する場合、結構手放せないのがタスクの仕組みです。組み込みのコマンドはもちろん、バッチ処理から、ちょっとしたヘルパータスクなど、私はシステムを開発する上で結構使っています。
このタスクシステム、Symfony2ではどうなっているのでしょう?
用語としては、「タスク」ではなく「コマンド」という用語になっているようです。
コマンドはバンドル単位で作る
symfony 1.xでは、symfonyコアのタスク、プラグインのタスク、プロジェクトレベルのlib/taskにあるタスクが自動的に読み込まれていました。
Symfony2では、「アプリケーション」という概念が変更され、プラグインに近い「バンドル」という単位でアプリケーションも管理されるようになります。
そして、このバンドルという単位でコマンドが読み込まれます。
※Symfony2のコアもバンドルの1つで、他のバンドルと同じ様式でコマンドの一覧が読み込まれます。
具体的には、バンドルのルートディレクトリに「Command」というディレクトリで、「〜Command.php」というファイル名の、「Symfony\Component\Console\Command\Command」を継承したクラスが読み込まれます。
symfony 1.xのタスクとSymfony2のコマンドの比較
symfony 1.x | Symfony2 | |
---|---|---|
名称 | タスク | コマンド |
親クラス | sfBaseTask | Symfony\Component\Console\Command\Command |
ディレクトリ | (project)/lib/task、(plugin)/lib/task | (bundle)/Command |
ファイル名 | 〜Task.class.php | 〜Command.php |
コマンド登録処理の流れ
- app/console - Applicationのインスタンス化
- Symfony\Bundle\FrameworkBundle\Console\Application __construct()
- Symfony\Bundle\FrameworkBundle\Console\Application registerCommands()
- 登録されているバンドルの一覧をforeach
- バンドルごとにregisterCommands()
- (各バンドルでオーバーライドされていなければ)Symfony\Component\HttpKernel\Bundle\Bundle registerCommands()
- 登録されているバンドルの一覧をforeach
<?php public function registerCommands(Application $application) { if (!$dir = realpath($this->getPath().'/Command')) { return; } $finder = new Finder(); $finder->files()->name('*Command.php')->in($dir); $prefix = $this->namespacePrefix.'\\'.$this->name.'\\Command'; foreach ($finder as $file) { $r = new \ReflectionClass($prefix.strtr($file->getPath(), array($dir => '', '/' => '\\')).'\\'.basename($file, '.php')); if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract()) { $application->addCommand($r->newInstance()); } } }
- ReflectionClass PHP: ReflectionClass - Manual