Fi1osof 26 ноября 2015 2 0
Довольно интересная задачка сегодня встала: есть каталог с радиаторами и вентилями (различаются по шаблону). В каталоге есть возможность вывести отдельно радиаторы, отдельно вентили, а можно сразу выводить все товары скопом. Так вот, возникла задача фильтровать радиаторы по отдельным параметрам, при этом иметь возможность выводить сразу и товары, и вентили. При этом у вентилей, понятное дело, даже нет тех параметров, по которым будут фильтроваться радиаторы. Как же сделать выборку так, чтобы учесть условия отдельно для радиаторов, отдельно для вентилей, и при этом иметь общие условия (опубликован, не скрыт в меню, не удален), да еще и не плодить SQL-запросы?

xPDO-запрос получился такой:
public function prepareQueryBeforeCount(xPDOQuery $c) {
        $c = parent::prepareQueryBeforeCount($c);
        
        $alias = $c->getAlias();
        
        // Поиск по модели радиатора
        $radiators_where = array();
        
        if($radiator_model_id = $this->getProperty('radiator_model_id')){
            
            $categories = array();
                
            $this->getCategories($radiator_model_id, $categories);
            
            if($categories){
                $radiators_where['parent:IN'] = $categories;
            }
            
            unset($categories);
        }
        
        if($radiator_height = (int)$this->getProperty('radiator_height')){
            
            $c->leftJoin('modTemplateVarResource', 'tv_radiator_height', "tv_radiator_height.tmplvarid = 4 AND tv_radiator_height.contentid = {$alias}.id");
            $radiators_where[] = "CAST(tv_radiator_height.value as UNSIGNED) <= {$radiator_height}";
            
        }
        
        if($radiators_where){
            $c->where(array(
                array(
                    "template"  => 5,
                    $radiators_where,
                ),
                "OR:template:!="   => 5,
            ));
        }
        
        return $c;
    }


Если у нас не переданы специальные условия для фильтра радиаторов, то у нас формируется обычный запрос:
SELECT modResource.* 
    FROM `modx_site_content` AS `modResource` 
    JOIN `modx_shopmodx_products` `Product` 
        ON `modResource`.`id` =  `Product`.`resource_id` 
    WHERE  ( 
        `modResource`.`deleted` = 0 
        AND `modResource`.`hidemenu` = 0 
        AND `modResource`.`published` = 1 
)


А если мы передадим в вызов «radiator_height» => 350, то получим такой:
SELECT modResource.* 
    FROM `modx_site_content` AS `modResource` 
    JOIN `modx_shopmodx_products` `Product` 
        ON `modResource`.`id` =  `Product`.`resource_id` 
    LEFT JOIN `modx_site_tmplvar_contentvalues` `tv_radiator_height` 
        ON tv_radiator_height.tmplvarid = 4 AND tv_radiator_height.contentid = modResource.id
    WHERE  (
        ( 
            `modResource`.`deleted` = 0 
            AND `modResource`.`hidemenu` = 0 
            AND `modResource`.`published` = 1 
        ) 
        AND  
        (  
            (
                 `modResource`.`template` = 5 
                AND CAST(tv_radiator_height.value as UNSIGNED) <= 350 
            )  
            OR `modResource`.`template` != 5 
        )
    )

Обратите внимание, что у нас есть один обособленный блок условий по статусам публикации, и есть второй блок, в котором условия прописаны буквально «где шаблон 5 И Все условия по радиаторам ИЛИ шаблон не 5».

Таким образом мы можем составлять довольно сложные запросы индивидуально для радиаторов, и отдельно для всех товаров в целом.

Вот более сложная выборка, если мы передаем такие параметры:
$params = array(
    "radiator_height"   => 650,
    "radiator_depth"   => 200,
    "radiator_model_id" => [
        1248,
        19,
    ],
    "where" => [
        "template"  => 5,
    ],
);

В данном случае мы запросили только радиаторы (добавив условие по шаблону), указали определенные модельные линейки радиаторов (параметр radiator_model_id) и максимальную высоту и глубину секций. Вот такой SQL-запрос получился:
SELECT 
	modResource.* 
	FROM `modx_site_content` AS `modResource` 
	JOIN `modx_shopmodx_products` `Product` ON `modResource`.`id` =  `Product`.`resource_id` 
	LEFT JOIN `modx_site_tmplvar_contentvalues` `tv_radiator_height` 
            ON tv_radiator_height.tmplvarid = 4 AND tv_radiator_height.contentid = modResource.id 
	LEFT JOIN `modx_site_tmplvar_contentvalues` `tv_radiator_depth` 
            ON tv_radiator_depth.tmplvarid = 7 AND tv_radiator_depth.contentid = modResource.id 
	WHERE  
		(  
			( 
				`modResource`.`deleted` = 0 
				AND `modResource`.`hidemenu` = 0 
				AND `modResource`.`published` = 1 
			)  
			AND  
			(  
				( 
					`modResource`.`template` = 5 
					AND  
					( 
						`modResource`.`parent` IN (1248,19,27,230,1249) 
						AND CAST(tv_radiator_height.value as UNSIGNED) <= 650 
						AND CAST(tv_radiator_depth.value as UNSIGNED) <= 200 
					)  
				)  
			OR `modResource`.`template` != 5 
			)  
		)


0 комментариев
Авторизуйтесь или зарегистрируйтесь (можно через соцсети ), чтобы оставлять комментарии.