Фильтры в интернет-магазине. Урок 4. Пишем базовый 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[0]; $sortDir = $sort[1]; 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 тысяч.
И отсортированы товары уже наоборот. Если Вы все сделали правильно, то увидите точно такую же картинку.
Вы можете еще поиграть с консолью и убедиться, что данные возвращаются корректно. В конце концов, самое важное - это добиться правильной работы фильтров, возврата правильного списка товаров. Раскидать полученные данные по странице, с учетом уже готовой верстки - дело внешне самое интересное, но с точки зрения разработки достаточно простое. Но не буду забегать вперед - подробности в следующем уроке.
Предыдущий урок серии -
Фильтры в интернет-магазине. Урок 3. Как собрать данные на клиенте и отправить их на сервер
Следующий урок -
Фильтры в интернет-магазине. Урок 5. Принимаем данные с сервера и отображаем их на клиенте
Все об интернет-магазинах
- Демо интернет-магазина
- Корзина интернет-магазина. С чего все началось
- Оформляем заказ на клиенте и сервере
- Добавляем доставку
- Фильтры и сортировки на клиенте и сервере
- Урок 0. Вводный
- Урок 1. Структура базы данных
- Урок 2. Структура проекта и верстка
- Урок 3. Сбор данных на клиенте и отправка на сервер
- Урок 4. Пишем базовый php-код и sql-запросы
- Урок 5. Прием данных с сервера и рендеринг на клиенте
- Урок 6. Заключительный, дорабатываем некоторые штрихи
- Сравнение товаров
- Постраничная навигация по товарам
- Преобразуем каталог, переключаем внешний вид товаров одной кнопкой
- Отправка sms при оформлении заказа
- Админка интернет-магазина на vue.js - серия уроков
- Авторизация на сессиях. Делаем логин в админке
- Docker для начинающих. Докеризуем интернет-магазин
Истории из жизни айти и обсуждение кода.