Блог веб-программиста

28Апр/120

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. Будем надеяться, что разработчики предусмотрят достойную замену.

Связано с категорией: Code Нет комментариев