Yii: CStatRelation и defaultScope у реляций
Ночью столкнулся с внезапной проблемой в Yii Framework 1.
Оказывается, статистические запросы через CStatRelation не поддерживает scopes в параметрах. Так что, если мы имеем defaultScope в нашем связанно элементе, то отменить его действие мы не сможем.
Как повторить эту проблему. Допустим имеем класс RevisionsSets с таким вот определением реляций:
/** * @return array relational rules. */ public function relations() { return array( 'pricesCount'=>array( self::STAT, 'Revisions', 'revisionSetId', ), ); } |
Ну и в самом классе Revisions имеем следующую группу условий по-умолчанию:
public function defaultScope() { $rev = Config::model()->getConfigValue("Shop", "CurrentRevision")->value; $t = $this->getTableAlias(false, false); return array( 'condition' => "$t.revisionSetId=:rev", 'params' => array('rev'=>$rev), ); } |
Что же происходит при вызове $revisionsSetModel->pricesCount
?
STAT-реляция забирает количество записей, но при этом применяет defaultScope от модели Revisions и в итоге для всех экземпляров RevisionsSets считается некорректное количество записей.
Исправить такое поведение можно было бы допливанием CStatRelation и реализацией там поддержки условий, как это например сделано в HAS_MANY, MANY_MANY, BELONGS_TO.
Но мне в голову пришел более быстрый вариант. Я создал класс RevisionsResetScope, который наследует Revisions и переопределяет defaultScope:
<?php class RevisionsResetScope extends Revisions { public function defaultScope() { return $this->resetScope(); } } |
Этот класс и используем в реляции:
/** * @return array relational rules. */ public function relations() { return array( 'pricesCount'=>array( self::STAT, 'RevisionsResetScope', 'revisionSetId', ), ); } |
Вот такой костыль. Кстати, на форуме Qiang Xue решил отказаться от статистических запросов и CStatRelation в Yii Framework 2. Будем надеяться, что разработчики предусмотрят достойную замену.