symfony1.4でview.ymlの拡張を行う

Author:Shogo Kawahara <kawahara@bucyou.net> Twitter: @ooharabucyou
Date:2010-12-05
License:Creative Commons Attribution 3.0 Unported License

Symfony アドベントカレンダー2010 の5日目です。

<-4日目 5日目(今ここ) 6日目->

概要

symfonyの設定ファイルは柔軟性が高くて好きです。YAMLが気に食わないと思えば Configuration Handler を変えることでそれが実現できます。

今回は、元からある view.yml の Configuration Handler を魔継承してオレオレルールを作りましょう。

実際の作業

view.ymlのConfigHandler

view.yml の デフォルトの Configuration Handler を少し覗きます。

$sf_symfony_lib_dir/config/sfViewConfigHandler.class.php より引用

<?php

  class sfViewConfigHandler extends sfYamlConfigHandler
  {
    public function execute($configFiles)
    {
      // parse the yaml
      $this->yamlConfig = self::getConfiguration($configFiles);

      // init our data array
      $data = array();

      $data[] = "\$response = \$this->context->getResponse();\n\n";

      // 省略...

      // compile data
      $retval = sprintf("<?php\n".
                        "// auto-generated by sfViewConfigHandler\n".
                        "// date: %s\n%s\n",
                        date('Y/m/d H:i:s'), implode('', $data));

      return $retval;
    }

    // 以下省略

と、なんとかしてPHPのコードを生成して返しているのがわかります。

ここで返されたやつが、キャッシュになるわけですね。

なるほど。Configuration Handler がやることはわかりました。

Note

この仕組については

A Gentle Introduction to symfony | 第19章 - symfony の設定ファイルをマスターする

を読むと、より納得ができるかもしれません。

拡張

プロジェクトの config/config_handlers.yml を置いて、独自の Configuration Handler を設定するという手段もありますが、 僕は1つプラグインをつくって、いろいろなプロジェクトで使い回しをするというのが大好です。 つまり、 symfony プラグインを作成することにします。

とりあえず、今回は sfViewYamlExtraPlugin という名前にしました。 ちゃちゃっと使うディレクトリなどを用意します。

$ mkdir plugins/sfViewYamlExtraPlugin
$ cd plugins/sfViewYamlExtraPlugin
$ mkdir config
$ mkdir lib
$ mkdir lib/config

とりあえず例なので、 view.yml に記述された flag の設定値を取り出し、 sfConfigflag という設定として書きこむという簡単な拡張を書きます。

plugins/sfViewYamlExtraPlugin/lib/config/sfViewConfigHandlerExtra.class.php

<?php

class sfViewConfigHandlerExtra extends sfViewConfigHandler
{
  public function execute($configFiles)
  {
    // 通常の結果を取得 <?php ..... という形で来る
    // この処理は YAMLのロードを含むので最初にやる
    $pResult = parent::execute($configFiles);

    // sfViewConfigHandler のやり方を真似ています。
    $data = array();

    $first = true;
    foreach ($this->yamlConfig as $viewName => $values)
    {
      // all は無視
      if ($viewName == 'all')
      {
        continue;
      }

      // テンプレート用の設定がある場合
      $data[] = ($first ? '' : 'else ')."if (\$this->actionName.\$this->viewName == '$viewName')\n".
                "{\n";
      $data[] = $this->addFlag($viewName);
      $data[] = "}\n";
      $first = false;
    }

    $data[] = ($first ? '' : "else\n{")."\n";

    // デフォルトの設定
    $data[] = $this->addFlag();

    $data[] = ($first ? '' : "}")."\n";


    // 通常の結果と今回拡張したものを連結
    $retval = $pResult.sprintf(
                      "// auto-generated by sfViewConfigHandlerExtra\n%s\n",
                      implode('', $data));

    return $retval;
  }

  protected function addFlag($viewName = '')
  {
    // getConfigValue() で継承関係を配慮して設定値を取り出します
    $flag = $this->getConfigValue('flag', $viewName);

    if (null !== $flag)
    {
      return sprintf("  sfConfig::set('flag', %s);", var_export($flag, true))."\n";
    }

    return "";
  }
}

Note

PHPのコード生成途中で、$this を埋め込んでいます。 これは実際に動くときには sfPHPView のインスタンスになります。

sfPHPView::configure() を見ると、謎が解けるかもしれません。

plugins/sfViewYamlExtraPlugin/config/config_handlers.yml

modules/*/config/view.yml:
  class: sfViewConfigHandlerExtra
  file: %SF_PLUGINS_DIR%/sfViewYamlExtraPlugin/lib/config/sfViewConfigHandlerExtra.class.php

プラグインを有効にするのを忘れずに。

config/ProjectConfiguration.class.php のsetup()中に以下を追加

$this->enablePlugins('sfViewYamlExtraPlugin');

これで、view.yml に対して sfViewConfigHandlerExtra が使われるようになります。

試しに、どこかのモジュールの config/view.yml に、

all:
  flag: true

などと書いてみて、テンプレートで

<?php var_dump(sfConfig::get('flag')); ?>

とすると、設定した値が表示されます。

実用例

今回、例として作ったものは特に何に使えるか、ということを想定してないです。

幸いなことに、実際にこのテクニックを使ったものがあるので紹介します。

あとがき

皆が Symfony2 or Doctrine2 に飛び込んでいくなかで、まだまだ現役なsymfony1.4のネタをやらせていただきました! この情報が誰かの役にたったのならば嬉しいです。

次は hidenorigoto さんがやるようです。楽しみですね!

別で進行中の OpenPNE3.6 Advent Calendar も応援してください!

Symfony Advent 2010であなたの記事を公開してみませんか?

Symfony Advent 2010では12月1日から12月24日までを使って日替わりでsymfonyでイイなと思った小さなtipsから内部構造まで迫った解説などをブログ記事にして公開していくイベントです。

参加については ATND で参加表明の上、

GoogleGroupの Symfony Advent 2010 に追加リクエストを送信ください。

Symfony Advent 2010チーム一同、あなたの参加をお待ちしております。

Note

Symfony Advent 2010はsymfony好きな有志で集まったチームです。