Сегодня будет небольшой «хак» для ORM Yii2, если вы используете PGPool.
Да, это опять некие костыли (как и в первой моей статье), но мне кажется, что эти (учитывая победное шествие PostgreSQL) могут и пригодится даже большему числу людей.
Все кто работают с PGPool в режиме Master-Slave рано или поздно столкнутся с задачей, когда делать селекты надо непременно из мастера. Благо разработчики о нас позаботились и дали такую возможность. Кто видел схему работы PGPool меня поймут: пишем перед селектом нехитрую строчку /*NO LOAD BALANCE*/ и наш запрос PGpool отправит в мастер базу.
Проблемы начинаются тогда, когда нам нужно использовать ORM.
На примере Yii2 мы пока решили это так:
Переопределяем класс ActiveQuery и, главное, его метод createCommand()
А используем мы это так:
И, очень хочется, чтобы разработчики Yii все-таки как-то это сделали «внутри» из коробки.
Да, это опять некие костыли (как и в первой моей статье), но мне кажется, что эти (учитывая победное шествие PostgreSQL) могут и пригодится даже большему числу людей.
Все кто работают с PGPool в режиме Master-Slave рано или поздно столкнутся с задачей, когда делать селекты надо непременно из мастера. Благо разработчики о нас позаботились и дали такую возможность. Кто видел схему работы PGPool меня поймут: пишем перед селектом нехитрую строчку /*NO LOAD BALANCE*/ и наш запрос PGpool отправит в мастер базу.
Проблемы начинаются тогда, когда нам нужно использовать ORM.
На примере Yii2 мы пока решили это так:
Переопределяем класс ActiveQuery и, главное, его метод createCommand()
class ActiveQuery extends \yii\db\ActiveQuery { private $_noLoadBalance = false; /** * Не отправлять запрос на балансировщик, а прямо в мастер * * @return $this */ public function noBalance() { $this->_noLoadBalance = true; return $this; } /** * @inheritdoc */ public function createCommand($db = null) { /* @var $modelClass ActiveRecord */ $modelClass = $this->modelClass; if ($db === null) { $db = $modelClass::getDb(); } if ($this->sql === null) { list ($sql, $params) = $db->getQueryBuilder()->build($this); } else { $sql = $this->sql; $params = $this->params; } $comment = ''; if (true === $this->_noLoadBalance) { $comment = '/*NO LOAD BALANCE*/'; } return $db->createCommand($comment . $sql, $params); } }
А используем мы это так:
$user = User::find()->where([ User::ATTR_ID => $userid, ]) ->noBalance() ->one();
И, очень хочется, чтобы разработчики Yii все-таки как-то это сделали «внутри» из коробки.