symfonyで動的にDBを切り替える方法

あるデータは、現在使っているのとは別のデータベースに入れたいなぁ。
という時に便利なハックです。

DBの設定追加

databases.ymlにdatabase1用の設定(doctrine)が既にあるとして、新たにdatabase2用の設定を追加します。

all:
  doctrine:
    class: sfDoctrineDatabase
    param:
      dsn: 'mysql:host=localhost;dbname=database1'
      username: hoge
      password: huga
  database2:
    class: sfDoctrineDatabase
    param:
      dsn: 'mysql:host=localhost;dbname=database2'
      username: hoge
      password: huga

デフォルトのコネクション設定

例は、デフォルトをdoctrineにしたい場合です。

<?php
// apps/frontend/config/frontendConfiguration.class.php

class frontendConfiguration extends sfApplicationConfiguration
{
  public function initialize()
  {
    // load symfony autoloading first
    parent::initialize();

    // context.load_factoriesイベントが発火したら、下で定義するsetCurrentConnection()関数を
    // 呼ぶよう設定。Doctrineの初期化が終わった後に呼ばれるconfigureDoctrine()関数があるけれど、
    // この時点ではDBとのコネクション用設定ファイル(databases.yml)が読み込まれていないので、
    // この方法を取っている。
    // If load_factries event fire, call $this->setCurrentConnection() method.
    // When configureDoctrine() method is called, configuration file is not loaded yet
    // for the connection establishment.
    $this->getEventDispatcher()
         ->connect('context.load_factories', array($this, 'setCurrentConnection'));
  }

  public function configure()
  {
  }

  /**
   * Set default connection
   */
  public function setCurrentConnection(sfEvent $event)
  {
    Doctrine_Manager::getInstance()->setCurrentConnection('doctrine');
  }
}

別のデータベースへの繋ぎ方

いろいろ操作して、最後 save を呼ぶときに

save(Doctrine_Manager::getInstance()->getConnection('database2'));

と、繋ぎたいDBの名前のコネクション取得して、渡すだけです。


複数の操作がある場合は、

Doctrine_Manager::getInstance()->setCurrentConnection('database2');

で、一時的にコネクション先を変えるのもありです。
戻し忘れに注意

Taskの場合

タスクは、context.load_factoriesイベント取れなかったので、TasknameTask.class.phpのexecute内に

Doctrine_Manager::getInstance()->setCurrentConnection('database2');

を追加してあげてください。