Фильтр поиска товаров на PHP для интернет-магазина

Опубликовано: Комментариев: 0
Фильтр поиска товаров на PHP для интернет-магазина

Сегодня я расскажу как сделать фильтр товаров на php. В фильтре пользователь сможет выбирать множество параметров для сортировки и получать в ответ сгенерированный SQL запрос с результатами поиска. Итак, чтобы все работало на нужны 3 вещи:  

  1. База данных SQL с информацией для тестов
  2. PHP скрипт для обработки запроса и вывода результатов на страницу
  3. HTML форма фильтра товаров с полями сортировки
В данном уроке я покажу как сделать простейший вариант фильтра. В таком виде его еще нельзя использовать на сайте. Во-первых, нужно повысить безопасность запроса, добавить проверку данных, которые приходят от пользователя и конечно же добавить украшательств. За основу взята рабочая копия базы данных из моей самописной CMS и заполнена информацией о мобильных телефонах, их параметрах, ценах и т.д. в целях обучения. В этом уроке по созданию фильтра товаров на php мы будем использовать только 4 таблицы из базы:
  • items - артикул товара, название товара, наличие, цена обычная и цена по скидке
  • attribute_vendor - аттрибут "производитель" (Samsung, Lenovo, HTC и т.д.)
  • group_attribute_vendor - группа атрибутов содержит пары значений "код товара-код производителя"
  • item_photo - для 1 товара может быть 2 и более фотографии, поэтому тут я записываю информацию о коде товара и соответствующих ему фотографиях. Для основной фотографии ставлю 1 в поле item_photo_main.
Запустить DEMO | Скачать исхоники 1. HTML код фильтра товаров:
<form name="form" method="post">
  <ul>
    <li>Цена:
     <ul>
        <li><label for="filter_01">Цена от: </label><input id="filter_01" type="text" name="price_start"></li>
        <li><label for="filter_02">Цена до: </label><input id="filter_02" type="text" name="price_end"></li>
      </ul>
   </li>
   <li> Производитель:
     <ul>
        <li><input id="filter_03" type="checkbox" name="vendors[]" value="25"><label for="filter_03">Samsung</label></li>
       <li><input id="filter_04" type="checkbox" name="vendors[]" value="16"><label for="filter_04">Lenovo</label></li>
        <li><input id="filter_05" type="checkbox" name="vendors[]" value="26"><label for="filter_05">Sony</label></li>
        <li><input id="filter_06" type="checkbox" name="vendors[]" value="4"><label for="filter_06">Asus</label></li>
       <li><input id="filter_07" type="checkbox" name="vendors[]" value="8"><label for="filter_07">HTC</label></li>
      </ul>
   </li>
   <li><label for="filter_08">В наличии</label><input id="filter_08" type="checkbox" name="stock" value="1"></li>
    <li><label for="filter_09">Акционная цена</label><input id="filter_09" type="checkbox" name="discount" value="2"></li>
  </ul>
 <input type="submit" name="filter" value="Подобрать" />
</form>
Теперь PHP скрипт для создания SQL запроса:
<?php
 include '../inc/db.inc.php';
  function addFilterCondition($where, $add, $and = true) {
    if ($where) {
     if ($and) $where .= " AND $add";
      else $where .= " OR $add";
    }
   else $where = $add;
   return $where;
  }

 if (!empty($_POST["filter"])) {
   $where = "";
    if ($_POST["price_start"]) $where = addFilterCondition($where, "i.item_price >= '".htmlspecialchars($_POST["price_start"]))."'";
   if ($_POST["price_end"]) $where = addFilterCondition($where, "i.item_price <= '".htmlspecialchars($_POST["price_end"]))."'";
   if ($_POST["vendors"]) {
      $ids=$_POST["vendors"];
     $inQuery = implode(',', array_fill(0, count($ids), '?'));
     $where = addFilterCondition($where, 'vendors.attribute_id IN ('. $inQuery .')');
    }
   if ($_POST["stock"]) $where = addFilterCondition($where, "i.stock_id = 1");
   if ($_POST["discount"]) $where = addFilterCondition($where, "i.item_discount > 0");

    $sql = 'SELECT i.item_id, i.item_number, i.item_title, i.stock_id, i.item_price, i.item_discount, ph.item_photo, ph.item_photo_main, ph.item_photo_alt, ph.item_photo_title, vendors.attribute_id
      FROM (
        SELECT item_id, item_number, item_title, stock_id, item_price, item_discount
        FROM items
      )
     AS i
      LEFT JOIN item_photo AS ph ON i.item_number = ph.item_number
      LEFT JOIN group_attribute_vendor AS vendors ON vendors.item_number = i.item_number
      ';
   $second='ph.item_photo_main=0 ORDER BY i.item_id DESC'; 
    if ($where) $sql .= " WHERE $where AND ".$second;
   else $sql .= " WHERE ".$second;
   

  }
 echo '<h1>Получили такой SQL запрос:</h1>'.$sql;
  $stmt = $pdo->prepare($sql);
 $stmt->execute($ids);
  $no=$stmt->rowCount();
 echo '<h2>В результате найдено: '.$no.' строк </h2>';
?>
Единственный нюанс был в том, чтобы отправить значения с запятыми в PDO. Я имею ввиду передачу условия IN () для выбора нескольких производителей товара одновременно. Тут помогли запросы в Gogole такого формата: PHP PDO : How to call stored procedure to pass comma separated string to parameter Passing values to MySQL IN operation in PDO prepared statement bind an array to an IN() condition Вот который из способов решения в данном примере применил я:
$ids=$_POST["vendors"];
$inQuery = implode(',', array_fill(0, count($ids), '?'));
$stmt = $db->prepare('SELECT * FROM table WHERE id IN(' . $inQuery . ')');
Запустить DEMO | Скачать исхоники