コアのDIエクステンションでの設定を、自前のDIエクステンションで変更する

まず、DIエクステンションについては以下の記事を参照

このDIエクステンションですが、Symfony2コアの各バンドルごとのDIエクステンション自体を拡張するうまいやり方は今のところ分かっていないのですが、コアのDIエクステンションで行っているDIコンテナへの設定を、別のバンドルのDIエクステンションで変更する方法は分かりました。

単純なことなのですが、自分で作ったバンドルのDIエクステンションで、別のバンドルで行われている設定を変更するというだけです。

例:ビューテンプレートファイルの格納場所を変更する

ビューテンプレートのファイルは、デフォルトでは以下のようなディレクトリ・ファイルになっています。

\src\Application\HelloBundle\Resources\views\Hello\index.php

日本語で書くと、「バンドル内の、Resources\viewsディレクトリ以下のコントローラー名のディレクトリにある、アクション名.phpというファイル」が使われますが、このうち「ハンドル内の」や「Resources\views」ディレクトリは、FrameworkBundleの初期設定としてTemplatingのFilesystemLoaderに渡されています。

  • このような設定はDIコンテナを通して行われる
  • 設定値はDIコンテナに格納されている
  • 実際にTemplatingがインスタンス化されるのは、このサービスがDI経由でアクセスされた時点なので、だいぶ後
  • つまり、DIコンテナに格納された初期値群を何らかの方法で変更してやれば、Templatingの挙動などを思い通りにコントロールできます


1. TestBundleに「DependencyInjection」ディレクトリを用意し、「TestExtension.php」ファイルを作る

<?php
namespace Application\TestBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class TestExtension extends Extension
{
    public function configLoad($config, ContainerBuilder $container)
    {
        if (is_array($config['test']['templatepath']))
        {
            $dirs = $container->getParameter('templating.loader.filesystem.path');
            $dirs = array_merge($config['test']['templatepath'], $dirs);
            $container->setParameter('templating.loader.filesystem.path', $dirs);
        }
    }

    public function getXsdValidationBasePath()
    {
        return "";
    }

    public function getNamespace()
    {
        return 'http://www.symfony-project.org/schema/dic/symfony';
    }

    public function getAlias()
    {
        return 'test';
    }
}

DIコンテナの設定のうち「templating.loader.filesystem.path」に、テンプレートを探すパターン文字列のリストが設定されるので、その配列の先頭に追加しています。

また、getXsdValidationBasePath()、getNamespace()、getAlias()はExtensionインターフェイスでabstractになっているので実装しておく必要があるメソッドです。


2. このバンドルをAppKernelのregisterBundles()に追加する

<?php
    public function registerBundles()
    {
        $bundles = array(
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),

            // enable third-party bundles// register your bundlesnew Application\TestBundle\TestBundle(),
        );


3. config.ymlで、TestExtensionへの設定を記述する

test.config:
      test:
          templatepath:
              - '%kernel.root_dir%/views/%%controller%%_%%name%%%%format%%.%%renderer%%'

この設定だと、「app/views/Hello_index.php」というようなディレクトリ/ファイルが読み込めるようになります。

  • %1つで囲まれているものは、DIの設定へ落とし込まれる段階で実際の値に置き換えられます。
  • %2つで囲まれているものは、DIの設定へ落とし込まれる段階では%1つになり、実際に使われる段階の値が入ります。


4. アクションでのビューの指定

<?php
return $this->render('HelloBundle:Hello:index.php', array('name' => $name));

アクションでビューを描画する場合、必ず「:」で区切られた3つのパートを指定する必要があります。(パートが3つじゃないとエラーになります)

  1. バンドル名として解釈される = %%bundle%%
  2. コントローラー名として解釈される = %%controller%%
  3. テンプレート名(+フォーマット、レンダラー)として解釈される %%name%%、%%format%%、%%renderer%%