Фильтры в интернет-магазине. Урок 3. Собираем данные на клиенте и отправляем на сервер

август 24 , 2016
Предыдущая статья Следующая статья Демо Исходники

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


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

Все клиентские изменения коснутся файла catalogDB.js - в этом уроке мы будем работать только с ним. Так что откроем его и вспомним, что мы уже написали

    'use strict';
    
    // Модуль каталога для работы с БД
    var catalogDB = (function($) {
    
        var ui = {
            $prices: $('#prices'),
            $pricesLabel: $('#prices-label'),
            $minPrice: $('#min-price'),
            $maxPrice: $('#max-price')
        };
    
        // Инициализация модуля
        function init() {
            _initPrices({
                minPrice: 5000,
                maxPrice: 50000
            });
        }
    
        // Изменение диапазона цен
        function _onChangePrices(event, elem) {
            var minPrice = elem.values[0],
                maxPrice = elem.values[1];
            ui.$pricesLabel.html(minPrice + ' - ' + maxPrice + ' руб.');
            ui.$minPrice.val(minPrice);
            ui.$maxPrice.val(maxPrice);
        }
    
        // Инициализация цен с помощью jqueryUI
        function _initPrices(options) {
            ui.$prices.slider({
                range: true,
                min: options.minPrice,
                max: options.maxPrice,
                values: [options.minPrice, options.maxPrice],
                slide: _onSlidePrices
            });
        }
    
        // Экспортируем наружу
        return {
            init: init
        }
        
    })(jQuery);

Что же нам нужно сделать по клиентской части теперь? Для начала расширить объект ui, дополнив его новыми элементами. Затем навесить события на эти новые элементы и главное, написать функцию, которая собственно и собирает данные и отправляет их на сервер.

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

В общих чертах задача ясна. Теперь все по порядку.


Расширяем объект ui

В объекте ui у нас уже есть 4 поля, содержащие элементы, связанные с ценами. Мы завели их, когда подключали плагин jqueryUI.slider. Но кроме цен нам понадобятся еще:

  • 1. форма, которая и содержит в себе все элементы фильтров (нужна для сериализации содержащихся в них данных)
  • 2. кнопки категорий
  • 3. бренды, как общий контейнер, так и отдельные чекбоксы
  • 4. селект сортировки
После расширения выглядеть ui будет так:

    var ui = {
        $form: $('#filters-form'),
        $prices: $('#prices'),
        $pricesLabel: $('#prices-label'),
        $minPrice: $('#min-price'),
        $maxPrice: $('#max-price'),
        $categoryBtn: $('.js-category'),
        $brands: $('#brands'),
        $brandInput: $('#brands input'),
        $sort: $('#sort')
    };

Работаем с событиями

Для начала в функцию инициализации модуля добавим вызов метода _bindHandlers, сразу после инициализации цен.

    // Инициализация модуля
    function init() {
        _initPrices({
            minPrice: 5000,
            maxPrice: 50000
        });
        // Новая функция
        _bindHandlers();
    }

И напишем для нее реализацию

    // Навешиваем события
    function _bindHandlers() {
        ui.$categoryBtn.on('click', _changeCategory);
        ui.$brandInput.on('change', _getData);
        ui.$sort.on('change', _getData);
    }

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

    // Смена категории
    function _changeCategory() {
        var $this = $(this);
        ui.$categoryBtn.removeClass('active');
        $this.addClass('active');
        selectedCategory = $this.attr('data-category');
        _getData();
    }

Эти дополнительных операций всего две.
Во-первых, мы делаем активной выбранную кнопку категории, установив для нее сответствующий класс. А во-вторых, записываем id выбранной категории в глобальную (для этого модуля) переменную selectedCategory. Она нам еще понадобится, когда будем собирать данные для отправки на сервер. И в конце вызываем уже упоминавшуюся _getData.

И не забываем объявить переменную selectedCategory в начале модуля, сразу после объекта ui, и присвоить ей значение 0. selectedCategory = 0 означает, что выбран пункт "Все категории".

    var selectedCategory = 0;

Затем нам осталось навесить событие получения данных _getData на изменение цен.

    // Инициализация цен с помощью jqueryUI
    function _initPrices(options) {
        ui.$prices.slider({
            range: true,
            min: options.minPrice,
            max: options.maxPrice,
            values: [options.minPrice, options.maxPrice],
            slide: _onSlidePrices,
            change: _getData
        });
    }

Здесь последним параметром записывается change: _getData.

Готово, все события навешаны, теперь напишем главную на сегодня клиентскую функцию _getData


Отправка данных на сервер и получение ответа

А реализация _getData до ужаса проста и прямолинейна

    // Получение данных
    function _getData() {
        var catalogData = 'category=' + selectedCategory + '&' + ui.$form.serialize();
        $.ajax({
            url: 'scripts/catalog.php',
            data: catalogData,
            type: 'GET',
            cache: false,
            dataType: 'json',
            error: _catalogError,
            success: function(responce) {
                if (responce.code === 'success') {
                    _catalogSuccess(responce);
                } else {
                    _catalogError(responce);
                }
            }
        });
    }

Сначала мы записываем в переменную catalogData значения, сериализованные из формы, и добавляем заботливо сохраненный ранее id категории из переменной selectedCategory. А дальше идут стандартные параметры $.ajax. scripts/catalog.php - файл, который вытащит нам с сервера нужные данные. cache: false - отключаем кэш, нам нужны только свежие данные. dataType: 'json' - указывает тип данных, возвращаемых с сервера, чтобы не конвертировать строку json в объект голыми руками. Пока не написанные _catalogSuccess и _catalogError вызываются соответственно при успехе и ошибке ajax-запроса.

_catalogSuccess и _catalogError реализуем обычными заглушками. _catalogSuccess выдаст нам в консоли то, что вернул сервер, а _catalogError - информацию об ошибке.

    // Ошибка получения данных
    function _catalogError(responce) {
        console.error('responce', responce);
        // Далее обработка ошибки, зависит от фантазии
    }

    // Успешное получение данных
    function _catalogSuccess(responce) {
        console.log(responce);
    }

Для этого урока клиентского кода достаточно. Нам нужно еще написать небольшой php-скрипт.


Пишем php-код на сервере

Читатели, знакомые с предыдущими моими статьями про интернет-магазины, например, про оформление заказа на клиенте и сервере, узнают мою стандартную заготовку для php-скрипта. Код несложный, комментарии присутствуют.

    // Объявляем нужные константы
    define('DB_HOST', 'localhost');
    define('DB_USER', 'root');
    define('DB_PASSWORD', 'root');
    define('DB_NAME', 'webdevkin');
    
    // Подключаемся к базе данных
    function connectDB() {
        $errorMessage = 'Невозможно подключиться к серверу базы данных';
        $conn = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
        if (!$conn)
            throw new Exception($errorMessage);
        else {
            $query = $conn->query('set names utf8');
            if (!$query)
                throw new Exception($errorMessage);
            else
                return $conn;
        }
    }
    
    
    try {
        // Подключаемся к базе данных
        $conn = connectDB();
    
        // Возвращаем клиенту успешный ответ
        echo json_encode(array(
            'code' => 'success',
            'data' => $_GET
        ));
    }
    catch (Exception $e) {
        // Возвращаем клиенту ответ с ошибкой
        echo json_encode(array(
            'code' => 'error',
            'message' => $e->getMessage()
        ));
    }

Чтобы не углубляться в php на этом уроке, возвратим клиенту те же самые данные, что и получили с него в массиве $_GET. Только обернутые в json. Что с этими данными делать, как вытащить из MySql базы нужные товары с учетом фильтров и сортировок, мы разберем на следующем уроке. А пока можете убедиться, что мы все сделали правильно. Откройте консоль браузера, вкладку Network - XHR, меняйте категории, цены, сортировки и смотрите, как все нужные данные отправляются get-запросом на сервер и они же возвращаются на клиент в виде json-объекта. Webdevkin. Фильтры в интернет-магазине. Отправка данных на сервер и получение ответа


Нужные ссылки

На этом сегодня все. Предыдующие уроки из этой же серии:

UPDATED: следующий урок опубликован - Урок 4. Пишем базовый php-код

Все об интернет-магазинах

Предыдущая статья Следующая статья Демо Исходники
Заходите в группу в контакте - https://vk.com/webdevkin
Анонсы статей, обсуждения интернет-магазинов, vue, фронтенда, php, гита.
Истории из жизни айти и обсуждение кода.
Как Вам статья? Оцените!