Фильтры в интернет-магазине. Урок 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 для начинающих. Докеризуем интернет-магазин
Истории из жизни айти и обсуждение кода.