Как добавить доставку в интернет-магазине
Этот пост будет дополнением к статье Реализуем оформление заказа в интернет-магазине. Предполагается, что читатель знаком с материалом и кодом оной статьи. Мы рассмотрим, как добавить возможность выбора вариантов доставки при оформлении заказа, как рассчитать общую стоимость заказа для покупателя, как отправить эти данные на сервер и отобразить в письме. И для небольшого разнообразия сделаем бонус для покупателя в виде бесплатной доставки при большой сумме покупок.
Подумаем, что нам нужно в целом
Нужно, чтобы в форме заказа появился пункт "Способ доставки".
Пусть это будет набор радиокнопок со значениями, например: самовывоз, в пределах КАД и почтой России.
Самовывоз у нас будет бесплатный, доставка в пределах КАД и почтой соответственно 200 и 300 рублей.
Покупатель должен видеть, во сколько ему обойдется доставка отдельно и весь заказ в целом.
Выглядеть это будет примерно так:
При этом если сумма заказа превышает 10 000 рублей, то мы подарим клиенту бесплатную доставку и выдадим ему соответствующее сообщение
Когда клиент заполнит все нужные поля и отправит нам заказ, нужно будет добавить несколько строк в письмо. Это будет способ доставки, ее сумма и общая сумма заказа с доставкой
Что нужно сделать с кодом.
Всего 3 пункта:
- 1. добавить верстку в форму заказа
- 2. написать js-код для расчета стоимости и вывода ее покупателю
- 3. принять новые данные на сервере и отобразить их в письме.
Давайте же это сделаем.
Добавляем верстку
Открываем страницу, где содержится форма отправки заказа - order.html и добавляем в нее несколько строчек, сразу после телефона.
Что здесь понаписано?
Обычный бутстраповский код формы с радиокнопками. Из интересного то, что мы добавили 3 скрытых инпута,
delivery_type, delivery_summa и full_summa, куда соотвественно будем записывать нужные данные при загрузке формы и смене варианта доставки.
Можно было обойтись и без этих полей и вычислить их непосредственно при отправке заказа.
Но на мой взгляд такой способ удобнее тем, что нам не придется править код отправки заказа, все новые данные подхватит метод serialize().
Класс js-delivery-type радиокнопкам введен для удобства отслеживания изменений их значений. Атрибуты data-type и data-summa указывают способ доставки и его сумму соответственно (и записываются в инпуты delivery_type и delivery_summa). У первой кнопки стоит атрибут checked - отметим самовывоз по умолчанию. div id="alert-delivery" - это поле для информации о доставке, сумме или сообщению о ее бесплатности.
Пишем javascript-код
Открываем модуль order.js и думаем, что нужно изменить в нем. Во-первых, в объект ui нужно дописать новые элементы.
var ui = { // ... // Выше старые элементы // Дописываем новые $fullSumma: $('#full-summa'), $delivery: { type: $('#delivery-type'), summa: $('#delivery-summa'), btn: $('.js-delivery-type'), alert: $('#alert-delivery') } };
Вспомним, что мы хотим добавить небольшой функционал, дающий бесплатную доставку при больших суммах заказа. Введем новый объект для этого
var freeDelivery = { enabled: false, summa: 10000 };
Поле enabled будет true, если стоимость товаров в корзине превышает сумму, указанную в поле freeDelivery.summa.
Чтобы как можно меньше вмешиваться в уже написанный код, добавим метод _initDelivery().
// Инициализация доставки function _initDelivery() { // Устанавливаем опцию бесплатной доставки freeDelivery.enabled = (cart.getSumma() >= freeDelivery.summa); // Навешиваем событие на смену способа доставки ui.$delivery.btn.on('change', _changeDelivery); _changeDelivery(); }
Всего 3 простых строчки. В первой мы узнаем, не срабатывает ли для покупателя бесплатная доставка. Во второй при смене способа доставки запускаем метод _changeDelivery для пересчета всех сумм и вывода пользователю соответствущей информации. А в третьей запускаем этот самый метод, чтобы он сработал сразу после загрузки формы.
И да, конечно, не забываем включить _initDelivery() в общий метод загрузки страницы init()
// Инициализация модуля function init() { _renderMessage(); _checkCart(); // Новый метод инициализации доставки _initDelivery(); _bindHandlers(); }
Теперь осталось самое главное - написать код для _changeDelivery. Сначала код, потом его разберем.
// Меняем способ доставки function _changeDelivery() { var $item = ui.$delivery.btn.filter(':checked'), deliveryType = $item.attr('data-type'), deliverySumma = freeDelivery.enabled ? 0 : +$item.attr('data-summa'), cartSumma = cart.getSumma(), fullSumma = deliverySumma + cartSumma, alert = freeDelivery.enabled ? 'Мы дарим Вам бесплатную доставку!' : 'Сумма доставки ' + deliverySumma + ' рублей. ' + 'Общая сумма заказа: ' + cartSumma + ' + ' + deliverySumma + ' = ' + fullSumma + ' рублей'; ui.$delivery.type.val(deliveryType); ui.$delivery.summa.val(deliverySumma); ui.$fullSumma.val(fullSumma); ui.$delivery.alert.html(alert); }
Определим все нужные нам данные: $item - выбранная радиокнопка со способом доставки. deliveryType - способ, deliverySumma - логично, сумма. Но сумму мы не просто берем из data-атрибута, а предварительно проверив, не отработала ли бесплатная доставка. Если отработала, то ставим 0. cartSumma - стоимость всех товаров из корзины (кто не знает, в чем дело и что это за cart, то вот статья, с которой все началось). fullSumma - понятно, общая стоимость, доставка + товары. alert - сообщение, выводимое покупателю. Или радуем его бесплатной доставкой, или расписываем полностью суммы.
Последний блок из 4-х строк записывает нужные переменные в скрытые инпуты и текст сообщения в открытый div.
Это была, пожалуй, самая сложная часть статьи. Теперь на сервер будут отправляться новые данные о доставке, осталось лишь принять их и добавить в текст письма.
Принимаем данные на сервере и отправляем их в письмо
А это самое простое. В скрипте order.php, в функции getData(), там, где возвращается массив данных из $_POST, добавим всего 3 строчки:
// Подготавливаем данные function getData($conn) { return array( 'name' => getParam('name', $conn, 'noname'), 'email' => getParam('email', $conn, 'unknown email'), 'phone' => getParam('phone', $conn), 'address' => getParam('address', $conn), 'message' => getParam('message', $conn), // begin, Блок с новыми данными 'delivery_type' => getParam('delivery_type', $conn), 'delivery_summa' => getParam('delivery_summa', $conn), 'full_summa' => getParam('full_summa', $conn), // end, Блок с новыми данными 'cart' => isset($_POST['cart']) ? stripslashes($_POST['cart']) : '[]' ); }
А в email_order.php - шаблон письма - еще несколько строк
Доставка:
Сумма доставки: рублей
Итого с доставкой: рублей
Лучше всего добавить будет в конец письма, сразу после таблицы со списком товаров.
Updated: парсер кода в очередной раз чудит, добавляя html-комментарии к php-вставкам.
Смотрите правильный вариант в исходниках.
На этом все! В этот раз кода получилось даже меньше, чем разговоров о нем.
Нужные ссылки и статьи
Ссылка на демонстрационный магазин - вот здесь
Обновленный вариант исходников с добавлением доставки лежит по старому адресу - здесь.
Я решил не делать версионирование исходников сообразно статьям, потому как чтобы понять код любой статьи, все равно нужно прочитать все предыдущие уроки. Поэтому по указанной ссылке всегда будут лежать исходники, содержащие последнюю и полную версию нашего интернет-магазина. И конечно, архив будет регулярно обновляться с выходом новых статей по этой теме.
Все об интернет-магазинах
- Демо интернет-магазина
- Корзина интернет-магазина. С чего все началось
- Оформляем заказ на клиенте и сервере
- Добавляем доставку
- Фильтры и сортировки на клиенте и сервере
- Урок 0. Вводный
- Урок 1. Структура базы данных
- Урок 2. Структура проекта и верстка
- Урок 3. Сбор данных на клиенте и отправка на сервер
- Урок 4. Пишем базовый php-код и sql-запросы
- Урок 5. Прием данных с сервера и рендеринг на клиенте
- Урок 6. Заключительный, дорабатываем некоторые штрихи
- Сравнение товаров
- Постраничная навигация по товарам
- Преобразуем каталог, переключаем внешний вид товаров одной кнопкой
- Отправка sms при оформлении заказа
- Админка интернет-магазина на vue.js - серия уроков
- Авторизация на сессиях. Делаем логин в админке
- Docker для начинающих. Докеризуем интернет-магазин
Истории из жизни айти и обсуждение кода.