Фильтр поиска на PHP. Фильтр поиска на PHP Возвращаем товары клиенту

Несомненно, все владельцы интернет-магазинов стремятся сделать интерфейс своего проекта наиболее удобным и досконально продумывают его юзабилити, а также прочие аспекты. Одной из таких ситуаций является метод фильтрации товаров в интернет-магазинах созданных на платформе uCoz.

Чем отличается этот фильтр от стандартного? Данный скрипт позволяет использовать дополнительные поля товара для фильтрации. Все, что вам нужно, это открыть страницу редактирования товара и заполнить эти поля.

Меню фильтрации выводится на странице каталога товаров. Фильтровать товары можно по 9-ти признакам. В разных категориях признаки могут быть разные. Например, в категории "Смартфоны" вы можете вывести признак "Разрешение экрана", а в других категориях с аксессуарами к смартфону такой признак не нужен и вы можете его не выводить. Там будут другие девять признаков.
Опишем далее этот пример. У признака "Разрешение экрана" может быть несколько значений. Чтобы отфильтровать весь каталог по разрешению экрана, нужное разрешение отмечается галочкой. Чтобы вывелись смартфоны с любым разрешением, можно отметить галочкой пункт "Все".

Кроме того, фильтровать товары можно по цене (от-до) и по производителю. "Производитель" - это десятый признак, который доступен во всех категориях (если у товаров это поле заполнено).

Что даёт этот скрипт для КЛИЕНТА?

Последовательный алгоритм обдуманных шагов к свершению покупки и, как следствие, удовлетворение покупательской потребности. Демонстрируя клиенту доступные опции, фильтр помогает ему определиться с точным выбором приобретения. Таким образом ваш покупатель точно не будет сожалеть о совершенном выборе, его лояльность к магазине повысится и он непременно захочет вернуться снова.

Что даёт этот скрипт для ПРОДАВЦА?

Превращение разового клиента в постоянного покупателя, что обеспечивает расширение клиентской базы. Посещаемость сайта увеличивается и это не останется незамеченным поисковиками, позиции сайта поднимаются, положительные отзывы о магазине увеличиваются, прибыль возрастает, а значит изначальная задача создания интернет-магазина на пути успеха.

Фильтры призваны для того, чтобы отсортировать товар по определенным значениям указанным во время добавления товара и упростить поиск для потенциального покупателя. Но стандартные фильтры uCoz не позволяют выбрать несколько значений для фильтрации товаров. Наш скрипт фильтров решает этот вопрос.

На выбор есть 5 вариантов выбора оформления регулятора цены!


А также несколько вариантов дизайна чекбоксов!



Предлагаем вам ознакомиться с видео-демонстрацией скрипта, а также представляем полный перечень базовых преимуществ :

  • кроссбраузерный, современно стилизованный скрипт. Отзывчивый функционал и динамичная работа синхронная действиям клиента. Скрипт работает только на странице категории (шаблон «каталог товаров» );
  • настройка плагинов необходимых для работы скрипта максимально упрощена и сводится к указанию "вкл./выкл." в файле настроек скрипта (config.php) ;
  • возможность множественного выбора значений для фильтрации товаров;
  • возможность настройки активности групп фильтров или отдельных значений (чекбокс);
  • любые стандартные поля в модуле интернет-магазин возможно сделать значением для фильтрации. Например, "есть в наличии/нет в наличии", "дополнительные поля 1-9" и так далее;
  • присутствует кнопка быстрого сброса значений фильтров;
  • возможность сворачивания и разворачивания блоков фильтра с запоминаем выбора на cookie;
  • возможность активации и деактивации слайдера выбора цены;
  • возможность активации и деактивации стилизованного скролл-бара;
  • удобная и полная стилизации фильтра. Вы сможете изменить размеры и цвет фона фильтра, слайдера цены, скролл-бара и чекбоксов;
  • выбранные значения для фильтрации товаров сохраняются и не будут сброшены при обновлении страницы;
  • присутствует кнопка быстрого сброса для полной очистки значений фильтров.
    Требования к установке:
  • активированное PHP.

Меня иногда просят рассказать, как делаются сложные фильтры поиска . Например, как он сделан на том же Яндекс.Маркете , где может быть сотня различных параметров отбора товаров? В этой статье я расскажу, как такое делается, ведь тут нет абсолютно ничего сложного. Всё это делается по единому принципу, о котором читайте дальше.

Для начала должна быть таблица, по которой будет идти поиск. Пусть это будет упрощённая таблица для ноутбуков:

  • id - уникальный идентификатор.
  • price - цена.
  • manufacturer - производитель.
  • wi-fi - наличие Wi-Fi .

Теперь разберём форму поиска:

































Цена от: рублей
Цена до: рублей
Производитель
Apple

Acer

ASUS

Наличие Wi-Fi:




Думаю, здесь, всё прозрачно. Единственное, что обратите внимание на manufacturers . Квадратные скобки означают, что в скрипт попадёт массив со всеми значениями, выбранными пользователем. Чтобы лучше это понять, просто выведите print_r($_POST) , тогда Вы всё поймёте.

Теперь разберём скрипт. В целях упрощения скрипта я не стал его усложнять скриптами, отвечающими за безопасность, и ограничился функцией htmlspecialchars() . Однако, в реальности, обязательно надо проверять всё, что приходит от пользователя, используя, например, регулярные выражения и/или встроенные функции проверки переменных на их значение.

Главная задача скрипта - "собрать" SQL-запрос на основе того, что пришло от пользователя :

function addWhere($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 = addWhere($where, "`price` >= "".htmlspecialchars($_POST["price_start"])).""";
if ($_POST["price_end"]) $where = addWhere($where, "`price` <= "".htmlspecialchars($_POST["price_end"])).""";
if ($_POST["manufacturers"]) $where = addWhere($where, "`manufacturer` IN (".htmlspecialchars(implode(",", $_POST["manufacturers"])).")");
if ($_POST["wifi"]) $where = addWhere($where, "`wifi` = "1"");
$sql = "SELECT * FROM `my_table`";
if ($where) $sql .= " WHERE $where";
echo $sql;
}
?>

Думаю, что с выполнением получившегося запроса и выводом результата проблем возникнуть не должно. Если это не так или в данном скрипте не всё понятно, то Вам тогда однозначно нужно сначала изучить это: .

Как видите, сложные фильтры реализуются в PHP очень просто. Что касается "красивых " скриптов, где двигаются всякие ползунки и сразу меняется результат - это всё то же самое, только запросы отправляются не через форму, а через Ajax , а затем принимается ответ от сервера с результатом, который динамически выводится через чистый JavaScript , либо с использованием jQuery .

Вот по такому принципу делается любой фильтр поиска на PHP .

Мы научились собирать данные на клиенте и отправлять их на сервер. А на сервере написали заглушку в том месте, где должны возвращаться товары, отфильтрованные по введенным параметрам. Сейчас мы избавимся от заглушки и напишем пару методов и запросов, которые вытаскивают из базы нужные товары и возвращают их клиенту. Урок достаточно короткий. Приступаем

Что будем делать?

Нам нужно выполнить всего 3 пункта:

  • 1. Получить данные с клиента и обработать их под нужды сервера. Например, проставить параметры по умолчанию
  • 2. Написать, собственно, сам код для извлечения товаров из базы. В первую очередь, подготовить sql-запрос
  • 3. Вернуть клиенту полученные данные

Получение данных с клиента

Вы можете спросить: для чего нужно выделять эту простую операцию отдельно, если все данные мы легко вытащим из массива $_GET?

Во-первых, для того, чтобы проставить значения по умолчанию. Нельзя полагаться на то, что клиент сам позаботится об этом.

Во-вторых, не все данные находятся в $_GET в пригодном для использования виде. Например, сортировку с клиента нам удобнее передавать одним параметром в виде поле_направление, например, price_asc. Но в sql-запросе это отдельные сущности, поэтому их нужно предварительно обработать.

Похожая ситуация и с брендами. На клиенте мы отправляем их в виде массива brands, и php их получает тоже как массив. Но для sql-запроса нужна строка - список брендов через запятую. Поэтому бренды тоже нужно дополнительно обрабатывать.

Итак, напишем функцию getOptions(), которая вытащит данные из $_GET и преобразует их в удобный нам вид. Почти все вводные я уже сообщил, поэтому сразу смотрим на готовый код.

// Получение данных из массива _GET function getOptions() { // Категория и цены $categoryId = (isset($_GET["category"])) ? (int)$_GET["category"] : 0; $minPrice = (isset($_GET["min_price"])) ? (int)$_GET["min_price"] : 0; $maxPrice = (isset($_GET["max_price"])) ? (int)$_GET["max_price"] : 1000000; // Бренды $brands = (isset($_GET["brands"])) ? implode($_GET["brands"], ",") : null; // Сортировка $sort = (isset($_GET["sort"])) ? $_GET["sort"] : "price_asc"; $sort = explode("_", $sort); $sortBy = $sort; $sortDir = $sort; return array("brands" => $brands, "category_id" => $categoryId, "min_price" => $minPrice, "max_price" => $maxPrice, "sort_by" => $sortBy, "sort_dir" => $sortDir); }

Здесь мы видим, что сначала получаем id категории. Если категория не передана, мы считаем category_id = 0. Минимальная цена будет 0, максимальная - 1 миллион. Если Ваш интернет-магазин продает плутоний (нефть китайцам, муравьев поштучно), то Вы всегда можете добавить нулей в нужную строку или на худой конец вести расчеты в евро.

Сортировку преобразуем по-другому. Отдельно вытаскиваем поле сортировки и параметр: asc или desc.

Обратите внимание, что во всех случаях мы не забываем подставлять значение по умолчанию, если нужный параметр не приехал с клиента. И теперь, когда все данные преобразованы, осталось только вернуть их из функции в ассоциативном массиве через return array(...)

Подготовка sql-запроса и извлечение данных из базы

Все данные подготовлены в нужном нам виде, теперь напишем запрос и выполним его. Этим будет заниматься функция getGoods($options, $conn). В параметрах она принимает $options - данные, подготовленные предыдущей функцией, и $conn - объект подключения к БД, который мы создали в предыдущем уроке . Наша задача - написать sql-запрос. В общем виде он выглядит так:

Select g.id as good_id, g.good as good, b.brand as brand, g.price as price, g.rating as rating, g.photo as photo from goods as g, brands as b where g.category_id = выбранная_категория and g.brand_id in (список_брендов_через_запятую) and g.brand_id = b.id and (g.price between минимальная_цена and максимальная_цена) order by поле_сортировки направление_сортировки

Мы извлекаем нужные поля, применив ряд условий where и указав нужную сортировку. С ценами и сортировкой вопросов нет, просто подставляем в соответствующие места запроса нужные значения. Но с категорией и брендами нужно быть повнимательнее и вот почему.

Каждый товар у нас всегда имеет категорию. Понятия нулевой категории в нашей базе данных нет - мы это сделали для своего же удобства, чтобы понимать, что пользователь в браузере не выбрал никакую категорию (или выбрал все - для нас это одно и то же). И в этом случае мы не должны включать в запрос строчку
g.category_id = выбранная_категория and
То же самое и с брендами, если они не выбраны, то соответствующую строку пропускаем. Вот как это выглядит в коде.

// Получение товаров function getGoods($options, $conn) { // Обязательные параметры $minPrice = $options["min_price"]; $maxPrice = $options["max_price"]; $sortBy = $options["sort_by"]; $sortDir = $options["sort_dir"]; // Необязательные параметры $categoryId = $options["category_id"]; $categoryWhere = ($categoryId !== 0) ? " g.category_id = $categoryId and " : ""; $brands = $options["brands"]; $brandsWhere = ($brands !== null) ? " g.brand_id in ($brands) and " : ""; $query = " select g.id as good_id, g.good as good, b.brand as brand, g.price as price, g.rating as rating, g.photo as photo from goods as g, brands as b where $categoryWhere $brandsWhere g.brand_id = b.id and (g.price between $minPrice and $maxPrice) order by $sortBy $sortDir "; $data = $conn->query($query); return $data->fetch_all(MYSQLI_ASSOC); }

Сначала мы извлекаем из массива $options переменные цен и сортировок - они просто вставляются в запрос без изменений. А для категории и брендов мы формируем строки $categoryWhere и $brandsWhere по принципу: нужное условие для секции where, если данные есть, и пустая строка если данных нет. Таким образом получился достаточно вменяемый sql-запрос, учитывающий все наши пожелания. Две последние строчки выполняют оный запрос и возвращают из функции массив из объектов с нужными полями. Осталось собрать все в кучу и отправить полученные товары обратно уже заждавшемуся клиенту/браузеру.

Возвращаем товары клиенту

Это самая простая часть урока. Посмотрим на заглушку, написанную в предыдущем уроке.

// Подключаемся к базе данных $conn = connectDB(); // Возвращаем клиенту успешный ответ echo json_encode(array("code" => "success", "data" => $_GET));

Заменим этот код на

// Подключаемся к базе данных $conn = connectDB(); // Получаем данные от клиента $options = getOptions(); // Получаем товары $goods = getGoods($options, $conn); // Возвращаем клиенту успешный ответ echo json_encode(array("code" => "success", "options" => $options, "goods" => $goods));

Мы добавили пару строк: функцией getOptions извлекли данные в переменную $options. Тут же использовали ее в получении товаров getGoods, результаты сохранили в $goods. И расширили ответ клиенту. Параметр data переименовали в options и вернули в него не содержимое $_GET, а уже преобразованные значения. И в параметре goods вернули массив полученных товаров.

На этом урок закончен. Пока мы не можем использовать эти данные на клиенте, отрисовать их в браузере - этим мы займемся на следующем уроке. Но всегда можем открыть консоль, потыкать кнопочки и галочки и убедиться, что сервер возвращает нам правильные товары.

Проверяем результаты работы

Выберем категорию Смартфоны и отметим бренды Apple и Samsung. В ответе увидим, что сервер вернул 3 товара, отсортированных по возрастанию цены

Теперь поставим минимальную цену в 20 тысяч и сменим сортировку на убывание цены
Как видно, теперь всего 2 товара - один самсунг отбросился из-за неподходящей по фильтрам цены в 17 тысяч. И отсортированы товары уже наоборот. Если Вы все сделали правильно, то увидите точно такую же картинку.

Вы можете еще поиграть с консолью и убедиться, что данные возвращаются корректно. В конце концов, самое важное - это добиться правильной работы фильтров, возврата правильного списка товаров. Раскидать полученные данные по странице, с учетом уже готовой верстки - дело внешне самое интересное, но с точки зрения разработки достаточно простое. Но не буду забегать вперед - подробности в следующем уроке.

1. Фильтрация и сортировка блоков «Quicksand»

Плагин позволяет красиво реализовывать фильтрацию и сортировку элементов на странице с обалденным эффектом. Чтобы посмотреть эффект, на странице демонстрации понажимайте сверху на кнопки сортировки и фильтра.

Это решение отлично подойдет для реализации фильтров в интернет-магазинах или для оформления страниц-портфолио.

3. jQuery плагин jCoverflip

Интерактивная фильтрация блоков по меткам. Подойдет для реализации страницы портфолио либо для страницы с товарами, разбитыми по категориям. Попробуйте в действии этот плагин, для этого достаточно произвести переход между метками, которые выполнены в виде меню. Он, наверняка, вам понравится.

Отлично подойдет для организации портфолио либо галереи на сайте. На демонстрационной странице нажимайте на ссылки вверху, чтобы увидеть результат работы плагина.

5. jQuery плагин «MobilySelect»

Плагин для фильтрации блоков: можно отображать либо все элементы, либо оставить блоки с каким-нибудь определенным классом. Фильтрация происходит с различными анимационными эффектами.

6. jQuery HTML5 портфолио

Реализация красивого портфолио с помощью jQuery и HTML5. Фишка портфолио в реализованном фильтре. Различные работы в портфолио отображаются в зависимости от выбранной категории.

Сегодня я расскажу как сделать фильтр товаров на 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.

1. HTML код формы фильтра товаров:

  • Цена:
    • Цена от:
    • Цена до:
  • Производитель:
    • Samsung
    • Lenovo
    • Sony
    • Asus
    • HTC
  • В наличии
  • Акционная цена

2. PHP код фильтра товаров, который создает итоговый SQL запрос для поиска:

function addFilterCondition($where, $add, $and = true) { if ($where) { if ($and) $where .= " AND $add"; else $where .= " OR $add"; } else $where = $add; return $where; } function getMainQuery() { return "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"; } if (!empty($_POST["filter"])) { $sql = getMainQuery(); $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"); } $second = "ph.item_photo_main=0 ORDER BY i.item_id DESC"; if ($where) { $sql .= " WHERE $where AND " . $second; } else { $sql .= " WHERE " . $second; } } echo "

Получили такой SQL запрос:

" . $sql; $stmt = $pdo->prepare($sql); $stmt->execute($ids); $resultsCount = $stmt->rowCount(); echo "

В результате найдено: {$resultsCount} строк

";

Единственный нюанс был в том, чтобы отправить значения с запятыми в 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 . ")");