Propel::getConnection()のREAD/WRITE

Propelって1.3から、コネクションのREAD/WRITEを切り替えられるようになっているじゃないですか。

<?php

// write
$master = Propel::getConnection(ArticlePeer::DATABASE_NAME, Propel::CONNECTION_WRITE);

// read
$slave = Propel::getConnection(ArticlePeer::DATABASE_NAME, Propel::CONNECTION_READ);

各Base系のPeerの中に定義されるdoSelect()とかdoCount()はREADを、doInsert()とかdoForceDelete()とかはWRITEを自動的にとってくるようになっていますよね。おーなんかPropelがんばってるとか思ってたんですけども。

切り替えてくれるのはいいとして、どうやって設定するのかわからなかったので調べてみたところ、PropelConfigurationに含まれる各コネクション情報にslavesってパラメータを指定しておくとどうやらそっちをみてくれるらしいということはわかりました。slavesがない場合は、READが指定された場合でもWRITEを見に行くようです。

それで、きっとdatabases.ymlで指定できるんだろうなーと思って調べていたら、どうやらできないみたい?ただEvent Dispatcher使えばとりあえずできそうだということはわかりました。databases.ymlにslavesがあれば、設定に追加するというだけの処理なんですけども。

# config/databases.yml
all:
  mydb:
    class:       sfPropelDatabase
    param:
      classname: PropelPDO
      dsn:       sqlite:/path/to/mydb_master.sqlite
      # ↓これ追加
      slaves:
        connection:
          -
            dsn: sqlite:/path/to/mydb_slave1.sqlite
          -
            dsn: sqlite:/path/to/mydb_slave2.sqlite
<?php
// config/ProjectConfiguration.class.php

class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
    $this->enablePlugins('sfPropelPlugin');

    # ↓これ追加
    $this->dispatcher->connect('propel.filter_connection_config', array($this, 'filterSlaveConnections'));
  }

  public function filterSlaveConnections(sfEvent $event, $parameters)
  {
    $database = $event['database'];

    if ($database->hasParameter('slaves')) {
      $parameters['slaves'] = $database->getParameter('slaves');
    }

    return $parameters;
  }
}

これでREADの場合はslavesのほうが読み込まれるようになるみたいです。ちなみにslavesの下に配列で複数コネクションしていしますけど、1つの場合はconnection: の中に接続設定を1つだけ書いても動きます。

そういえばPropel 1.5がでて、sfPropel15Pluginもstableになりましたね。あーこれDoctrineでみたことあるみたいな機能が色々追加されてますね。

個人的にはtoArray()で関連するオブジェクトの情報も引っ張ってこれるようになったのはすごく魅力的です。最初から実装していればこんなパッケージ作らなくて済んだのに。(ネタで作ったんですけど)

ちなみに上のREAD/WRITEの切り替えについてちゃんとした対応があるなら教えていただけると幸いです。

追記

symfony 1.3 + Propel 1.4 で MySQLレプリケーション - aki77の日記

上記のページをふとみて、最初何やってるかわからなかったんですけど、実際に動かしてみてわかったことがひとつ。通常databases.ymlにユーザ名をusernameで指定しますが、Propelのslavesってuserで指定しなきゃいけないんですね。勉強になります。