Выборка товаров с условиями для различных типов товаров

Довольно интересная задачка сегодня встала: есть каталог с радиаторами и вентилями (различаются по шаблону). В каталоге есть возможность вывести отдельно радиаторы, отдельно вентили, а можно сразу выводить все товары скопом. Так вот, возникла задача фильтровать радиаторы по отдельным параметрам, при этом иметь возможность выводить сразу и товары, и вентили. При этом у вентилей, понятное дело, даже нет тех параметров, по которым будут фильтроваться радиаторы. Как же сделать выборку так, чтобы учесть условия отдельно для радиаторов, отдельно для вентилей, и при этом иметь общие условия (опубликован, не скрыт в меню, не удален), да еще и не плодить 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 )
)