Сегодня будет небольшой «хак» для ORM Yii2, если вы используете PGPool.
Да, это опять некие костыли (как и в первой моей статье), но мне кажется, что эти (учитывая победное шествие PostgreSQL) могут и пригодится даже большему числу людей.
Все кто работают с PGPool в режиме Master-Slave рано или поздно столкнутся с задачей, когда делать селекты надо непременно из мастера. Благо разработчики о нас позаботились и дали такую возможность. Кто видел схему работы PGPool меня поймут: пишем перед селектом нехитрую строчку /*NO LOAD BALANCE*/ и наш запрос PGpool отправит в мастер базу.
Проблемы начинаются тогда, когда нам нужно использовать ORM.
На примере Yii2 мы пока решили это так:
Переопределяем класс ActiveQuery и, главное, его метод createCommand()
class ActiveQuery extends yiidbActiveQuery {
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 все-таки как-то это сделали «внутри» из коробки.
Автор: vladnevlad