@survivor2005

Как сделать запрос в MYSQL на выборку товаров по фильтру?

Делаю интернет магазин электроники на чистом пхп. Дошел до фильтров и встрял.
Суть думаю стандартная, есть фильтры у товаров в виде чекбоксов. Например хочу выбрать ноутбуки у которых 6 гигов памяти, 8 гигов и с процессором АМД, ну и т.д.
Есть таблица properties. В ней названия свойств.
6037736d610db363927679.png
Есть таблица значений этих свойств property_values
60377378551f4502645936.png
И таблица товаров.
603773842029c765497369.png

В общем, когда жмут на чекбоксы, приходит массив на обработку. Естественно, я не могу знать заранее сколько и чего придет, не знаю правильно или нет, пришлось сделать сперва строку запроса циклом, затем сформировать массив подстановок (тоже не знаю, дает ли это безопасность в данном случае). Я просто ничего другого не придумал. Может все делается по-другому. Вот код:
public static function findFilteredProducts(array $arr=[])
    {
        $request = '';
        
        if(!empty($arr)) {
            foreach($arr as $id => $value) {
                $request .= ' AND property_values.property_id=:'.$id;
                foreach($value as $val) {
                    $request .= ' AND property_values.value=:'.$val;
                }
            }
        }
        if(!empty($arr)) {
            foreach($arr as $id => $value) {
                $placeholder[':'.$id]=$id;
                foreach($value as $val) {
                    $placeholder[':'.$val]=$val;
                }
            }
        }
      
        
        $db = new Db;
        return $db->query('SELECT product.* FROM ' . self::TABLE . ', property_values WHERE property_values.product_id=product.id '.$request,
        $placeholder);
    }


Из вышеуказанного кода выходит такой результат:
( //Массив подстановок
    [:86] => 86
    [:8] => 8
    [:87] => 87
    [:AMD] => AMD
)
PDOStatement Object
( //Строка запроса
    [queryString] => SELECT product.* FROM product, property_values WHERE property_values.product_id=product.id  AND property_values.property_id=:86 AND property_values.value=:8 AND property_values.property_id=:87 AND property_values.value=:AMD
)

Работает только если выбрать 1 чекбокс, более одного не пашет уже, не выдает товары.
  • Вопрос задан
  • 77 просмотров
Пригласить эксперта
Ответы на вопрос 1
rozhnev
@rozhnev
Fullstack programmer, DBA, медленно, дорого
Вот вариант построения запроса:
<?php
$request = [
	87=>'AMD',
	86=>'8'
];

$filter = implode(' or ', array_fill(0, count($request), '(pv.property_id = ? and pv.value = ?)'));

$filter_values = [];

foreach($request as $key=>$val) {
	$filter_values[] = $key;
	$filter_values[] = $val;
}

$query = 'select p.* from products p
	join property_values pv on p.id = pv.product_id
	where  ' . $filter . ' 
	group by p.id, p.name
	having count(distinct pv.id) = ' . count($request);


Share PHP code
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы