низкоуровневый SQL запрос или ActiveRecord

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
SaintRu
Сообщения: 4
Зарегистрирован: 2020.05.13, 11:22

низкоуровневый SQL запрос или ActiveRecord

Сообщение SaintRu »

Есть 3 таблицы
shop_reg (id, category_id, reg_math, ...) - таблица регулярных выражений для групп товаров (содержит id родительского каталога)
shop_categories (id, ...) таблица категорий по алгоритму Nested Set
shop_products (id, category_id,...) таблица товаров

Задача стояла по id товара выбрать все регулярки (из shop_reg) которые назначены на группы товаров в дочерних каталогах.
Т.к. в ActiveRecord не силен, написал сначала запрос на чистом SQL,
все работает и быстро,
только низкоуровнево, и никак не могу переписать на AR, и является ли в Yii дурным тоном писать так код?

Код: Выделить всё

SELECT r.* FROM shop_reg AS r 
LEFT JOIN shop_categories c ON c.id=r.category_id WHERE 
c.lft <= (SELECT lft FROM shop_categories WHERE id=(SELECT category_id FROM shop_products WHERE id = 7480)) 
AND  
c.rgt >= (SELECT rgt FROM shop_categories WHERE id=(SELECT category_id FROM shop_products WHERE id = 7480))
З.Ы. в оригинале названия таблиц заменил на <NameClass>::tableName()

unknownby
Сообщения: 344
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: низкоуровневый SQL запрос или ActiveRecord

Сообщение unknownby »

В модели ShopProducts

Код: Выделить всё

public function getShopCategories() {
	return $this->hasOne(ShopCategories::tableName(), ['id' => 'category_id'])
		->alias('c');
}

public function getShopReg() {
	return $this->hasMany(ShopReg::className(), ['category_id' => 'id'])
		->alias('r')
		->viaTable(ShopCategories::tableName() . ' c', ['id' => 'category_id'], function ($query) {
               		$query
               			->andOnCondition(['<=', 'lft' , $this->shopCategories->lft])
               			->andOnCondition(['>=', 'rgt' , $this->shopCategories->rgt])
                	;
        	});
}
Метод getShopReg должен вернуть то, что тебе надо. Судя по твоему запросу.
Как альтернативу можно попробовать еще такой вариант.

Код: Выделить всё

public function getShopCategories() {
	return $this->hasOne(ShopCategories::tableName(), ['id' => 'category_id'])
		->alias('c');
}

public function getShopReg() {
	return $this->hasMany(ShopReg::className(), ['category_id' => 'id'])
		->alias('r')
		->joinWith(['shopCategories' => function(\yii\db\ActiveQuery $query){
                	return $query
                		->andOnCondition(['<=', 'lft' , $this->shopCategories->lft])
               			->andOnCondition(['>=', 'rgt' , $this->shopCategories->rgt]);
            	}] , false, 'LEFT JOIN');
}
P.S. Пример использования, где $id - идентификатор товара, который передается в actionView.
Просто как вариант проверки.

Код: Выделить всё

//контроллер
$model = ShopProducts::findOne($id);
return $this->render('view', [
	'model' => $model,
]);

//вьюха
$all_reg_math = '';
foreach($model->shopReg as $value){
	$all_reg_math .= empty($all_reg_math) ? $value->reg_math : ', ' . $value->reg_math;
}
echo $all_reg_math;

SaintRu
Сообщения: 4
Зарегистрирован: 2020.05.13, 11:22

Re: низкоуровневый SQL запрос или ActiveRecord

Сообщение SaintRu »

Спасибо.
Код заметно усложнился ;), но стал ближе к ооп, буду экспериментировать

Ответить