Symfony 2がGitHubに移行した件とConsole Componentについて

今年のはじめくらいに、Symfony 2のブランチがGitHubに移行されました。

we host an official Git repository on Github

symfony 1.x legacy website

以前、Symfony2について少しふれていますが、あれからまたひとつ、Componentが追加されています。

Console Component

Console ComponentはGitHubに移行したのと同時期くらいに追加されました。元々CLIという名前だったのですが、最近Consoleにリネームされました。

Consoleという名前が示すとおり、コマンドラインで何か処理を行うときに利用するComponentです。これまでSymfonyにはsymfonyコマンドが存在しており、symfonyコマンドを通じて、スケルトンの生成やデータベース操作、プラグインのインストール、キャッシュのクリアなどなど、様々な操作がコマンドラインから実行可能でした。

これらの操作はSymfonyではタスクと呼ばれ、タスクはsymfonyのコアが提供しているものの他にも、各プラグインが用意していたり、プロジェクトごとに作成することもできます。

Console Componentはコマンドラインからタスクを実行するためのフレームワークです。Consoleでは次のようなクラスを提供します

  • Application
  • Command
  • Input
  • Output
  • Shell
  • Tester

では簡単に紹介していきます。

Console\Application

Symfonyは各プロジェクトの中にfrontendやbackendなどのアプリケーションをつくりますが、それとは違います。これはSymfonyLithiumなどのコマンドを提供するアプリケーションを指すクラスになります。

例えばsymfonyコマンドを作る場合は以下のようになります。

#!/usr/local/bin/php-5.3.0
<?php
$symfonyLibDir = realpath(__DIR__ . '/../symfony/src');
require $symfonyLibDir . '/Symfony/Foundation/ClassLoader.php';

use Symfony\Foundation\ClassLoader;
$classLoader = new ClassLoader();
$classLoader->registerNamespace('Symfony', $symfonyLibDir);
$classLoader->register();


// Applicationを作成
use Symfony\Components\Console\Application;

$application = new Application($name = 'symfony', $version = '2.0.0');
$application->run();

これをsymfonyという名前で保存し、実行権限を与えて実行したのが次の図です。

コードの下の方でnew Applicationとしていますが、Applicationのコンストラクタにはアプリケーション名とバージョンを指定します。run()メソッドを実行すると内部で引数がパースされ、Commandが実行される仕組みになっています。

あとは自前でCommandをApplicationに追加したりしてあげればそのコマンド名を引数に追加すると動くようになります。

Console\Command\Command

Commandは実際に実行する処理です。デフォルトでlistとhelpという2つのCommandが用意されており、listはコマンドの一覧を、helpはヘルプを表示するコマンドです。Applicationに対して引数無しで実行した場合はlistが呼ばれるようになっています。

コマンド名は特定の名前空間でグルーピングすることが可能です。これは現在のsymfonyと同様の仕組みです。例えば現在のsymfonyでは、doctrineに関するタスクは全てdoctrineという名前空間に含まれています。名前空間の区切り文字は「:(コロン)」で、doctrine:buildやdoctrine:generate-moduleといったタスクが用意されています。

ではサンプルとして、引数をそのまま出力するEchoCommandを作成してみます。名前空間はfivestarにします。

<?php
namespace fivestar;

use Symfony\Components\Console\Command\Command;
use Symfony\Components\Console\Input\InputArgument;
use Symfony\Components\Console\Input\InputInterface;
use Symfony\Components\Console\Output\OutputInterface;

class EchoCommand extends Command
{
  protected function configure()
  {
    $this
      ->setDefinition(array(
        new InputArgument('value', InputArgument::REQUIRED),
      ))
      ->setName('fivestar:echo')
    ;
  }

  protected function execute(InputInterface $input, OutputInterface $output)
  {
    $output->write($input->getArgument('value'));
  }
}

基本的にはConsole\Command\Commandクラスを継承し、configure()とexecute()という2つのメソッドを定義します。configure()にはコマンドの引数やオプション、コマンド名、その他にも詳細情報やヘルプなどを定義可能です。

上記のコードはほぼ必要最低限のことしか記述していません。configure()の内部でsetDefinition()を呼び出してInputArgumentクラスを作成しています。これは名前が表すとおり、コマンドの引数です。コンストラクタの第2引数にInputArgument::REQUIREDという定数を渡していますが、これ以外にもオプショナルな引数を表すOPTIONALや配列を表すIS_ARRAYが定義されています。第1引数は取得するためのキーです。

実際の処理はexecute()に記述します。何となくわかるかと思いますが、$input->getArgument('value')でコマンド実行時に入力された引数を取得し、$output->write()で出力しています。

今回はこれをfivestarというディレクトリの中にEchoCommand.phpで保存しました。先ほど作成したファイルを以下のように修正してCommandをApplicationに追加します

<?php
// ...
use Symfony\Components\Console\Application;

$application = new Application($name = 'symfony', $version = '2.0.0');

require './fivestar/EchoCommand.php';
$application->addCommand(new fivestar\EchoCommand());

$application->run();

実行してみるとちゃんと動きました。

listコマンドを実行すると、ちゃんとAvailable commandsに含まれています。


Input/Output

名前の通りです。特に深く突っ込まなくてもいいと思います。たいていの場合、コマンドラインの引数にあたる「ArgvInput」と、php://stdoutをラッピングした「ConsoleOutput」を使うことになると思います。InputInterfaceとOutputInterfaceを実装してさえいれば何でも大丈夫です。Applicationのrun()にInputとOutputを引数として渡すことができるので、変えたい場合はそこに渡します。

Shell

今日追加されたのがこのShellです。これは対話式のインターフェースです。php -aと同じようなものです。

<?php
use Symfony\Components\Console\Application;
use Symfony\Components\Console\Shell;

$shell = new Shell(new Application('symfony', '2.0.0'));
$shell->run();

上記のようなコードを書くだけで対話式のシェルが出来上がります。

これのいいところは、コマンドや引数の自動補完機能がついているところと、シェル上で実行したコマンドの履歴を自動的に保存してくれるところです。

自動補完についてはよくあるTABを押すと補完してくれるというやつですね。お馴染みです。

コマンド履歴については、ホームディレクトリ直下に「.history_アプリケーション名」というファイルにコマンドの履歴を書き込んでくれるようになります。またシェル上で↑キーを押したりCtrl+Rで検索したりもできるようになります。

どちらもPHPのreadlineを活用して実装されています。

Tester

ApplicationTesterとCommandTesterの2つがあり、ApplicationとCommandの実行結果のテストを行うためのクラスのようです。テストをするときに。

      • -

といったところでConsole Componentの紹介は終わりです。内容はシンプルですが、様々なPHPアプリケーションで使えるのではないでしょうか。

今後もとりあえずSymfony 2の動向は追い続けていきますが、symfony 1とDoctrine 1に興味があまりわかなくなってきてしまいました・・・。まだまだSymfony 2がどうなるかはわかりませんが、とても楽しみです。