symfony 1.4 + Doctrine 1.2で必ず実行したいクエリーを記述するには

  • symfony 1.4(+Doctrine)で作ったアプリで、DBにMySQLを使うと、DB接続直後に必ず「SET NAMES 'UTF8'」が実行されます。
  • 同じように、DB接続時に決まったクエリーを発行したい場面がありましたので対応メモ。

実装

実装方針

  • 目的は、DB接続時に「set time_zone='+9:00'」を実行することです。
  • 接続後にクエリーを発行する機能を作成し、イベントリスナーとして登録します。
  • 「+9:00」部分は パラメータとしたいので、config/database.ymlに記述します。

config/databases.yml

  • 「+9:00」部分をパラメータ記述します。
  doctrine:
    class: sfDoctrineDatabase
    param:
      dsn:      mysql:host=localhost;dbname=hogehogedb
      username: hogehogeuser
      password: hogehogepassword
      timezone: '+9:00'

lib/myDoctrineConnectionListener.class.php

  • 接続時にクエリー実行する処理を作成します。
  • 接続後呼ばれるメソッドが postConnectです。
class myDoctrineConnectionListener extends Doctrine_EventListener
{
    /**
     * 接続後イベント
     *
     * @param Doctrine_Event $event event object
     *
     * @return null
     * @see Doctrine_EventListener::postConnect()
     */
    public function postConnect(Doctrine_Event $event)
    {
        $connection = $event->getInvoker(); /* @var $connection Doctrine_Connection */
        $time_zone = sfContext::getInstance()->getDatabaseManager()->getDatabase($connection->getName())->getParameter('timezone');
        $connection->execute(sprintf("SET time_zone = '%s';", $time_zone));
    }
}

  • database.ymlに追加した「timezone」パラメータの取得部分をキレイにできませんでした。connectionオブジェクトには保持していないんですね。
  • しかたないので、sfContextから引っ張りだしてます。

config/ProjectConfiguration.class.php

  • configureDoctrineConnectionDoctrineメソッドを記述し、イベントリスナーを登録します。
  • 全体の処理に適用するので、この「config/ProjectConfiguration.class.php」ファイルに記述します。
  • アプリごとに実行したい場合は、ProjectConfigurationを継承している apps/frontend/config/frontendConfiguration.class.phpなどに記述すると良いと思います。
class ProjectConfiguration extends sfProjectConfiguration
{
    // (setupメソッドは省略)

    /**
     * DB接続時の処理
     *
     * @param Doctrine_Connection $connection
     *
     * @return null
     * @see sfDoctrineDatabase::initialize()
     */
    public function configureDoctrineConnectionDoctrine(Doctrine_Connection $connection)
    {
        if ($connection->getDriverName() == 'Mysql') {
            $eventListener = new myDoctrineConnectionListener();
            $connection->addListener($eventListener);
        }
    }
}

実行結果

  • MySQLのトレースログで確認します。 →SQLトレースログ取得
  • 接続直後、期待通りのクエリーが実行されていることを確認します。
120422 16:39:54    84 Connect   hogehogeuser@localhost on hogehogedb
                   84 Query     SET NAMES 'UTF8'
                   84 Query     SET time_zone = '+9:00'

facebook slideshare rubygems github qiita