Задача. Необходимо совместить страницы Корзины и Оформления заказа. По сути на странице нужно вывести три основных блока: Таблица товаров (как в корзине), Детали заказа (телефон, адрес) и Заказ (оплата, цена и т.д.). Самая большая проблема заключалась в том, что по макету на странице две колонки — слева таблица товаров и под ней Детали заказа, а справа — блок Заказ. Но в шаблонах Woocommerce Таблица с товарами это одна форма, а Детали заказа с блоком Заказ — другая. И вынести Детали заказа из своей формы и вставить куда хочешь — не получится.
Решение. Проблема совмещения корзины с оформлением заказа состоит в том, что это две формы, и вынести какой-то один элемент из своей формы — нельзя. Разметку и стили оговаривать не будем, т.к. может быть различной. В конце покажу скрипт, с помощью которого мы сможем разместить нужные нам элементы в любой области. Для совмещения страниц Оформления заказа и Корзины использовал JS и изменения в шаблонах Woo, вот алгоритм:
- Используем страницу, которую Woocommerce создает по умолчанию по установки. Если по какой-то причине ее нет, то создаем новую и в настройках плагина привязываем ее как страница Оформления заказа.
- Ставим шорткод
[woocommerce_checkout]
на странице Оформления заказа. - Копировать из плагина файл шаблона формы оформления заказа
woocommerce/checkout/form-checkout.php
в дочернюю тему с такой же вложенностью. - Из файла корзины
woocommerce/cart/cart.php
копируем саму форму (таблицу с товарами) и хукdo_action( 'woocommerce_before_cart' );
, т.к. через него выводятся оповещения корзины. Вставляем форму корзины в нашform-checkout.php
, где нужно. - Вставляем там же JS-скрипт из Код №1. В данном случае мы создаем копию блока с деталями заказа, переносим под форму с таблицей товаров, оригинальные элементы скрываются и в них передаются данные из новых (скопированных) элементов.
- Если товары не добавлены в корзину, то при переходе на нашу страницу Оформления будет происходить перенаправление на страницу Корзины, где будет сообщение о том, что корзина пуста и предложение перейти в магазин. В
functions.php
используем Код №2, который будет перенаправлять сразу на нашу страницу Оформления заказа если в корзине есть товары, иначе как положено покажет страницу корзины с уведомлением.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<script> // Перенос Деталей под таблицу document.addEventListener("DOMContentLoaded", function() { // Клонирование блока customer_details var customerDetails = document.querySelector('#customer_details'); if (customerDetails) { var clonedDetails = customerDetails.cloneNode(true); customerDetails.style.display = 'none'; // Скрываем оригинальный блок var cartForm = document.querySelector('.woocommerce-cart-form'); cartForm.insertAdjacentElement('afterend', clonedDetails); // Добавляем клонированный блок после первой формы // Настраиваем передачу данных var originalInputs = customerDetails.querySelectorAll('input, select, textarea'); var clonedInputs = clonedDetails.querySelectorAll('input, select, textarea'); clonedInputs.forEach(function(clonedInput, index) { clonedInput.addEventListener('input', function() { originalInputs[index].value = clonedInput.value; }); }); } }); </script> |
Позже еще выяснилось, что в моем случае плагином выводилось дополнительно два чекбокса (для подтверждения согласия и отметка чтобы перезвонили). Копии этих двух полей не срабатывали. Вот, скрипт из Код №1.2 решил проблему.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
<script> // Перенос Деталей под таблицу document.addEventListener("DOMContentLoaded", function() { // Клонирование блока customer_details var customerDetails = document.querySelector('#customer_details'); if (customerDetails) { var clonedDetails = customerDetails.cloneNode(true); customerDetails.style.display = 'none'; // Скрываем оригинальный блок var cartForm = document.querySelector('.woocommerce-cart-form'); cartForm.insertAdjacentElement('afterend', clonedDetails); // Добавляем клонированный блок после первой формы // Настраиваем передачу данных для input, select, textarea var originalInputs = customerDetails.querySelectorAll('input, select, textarea'); var clonedInputs = clonedDetails.querySelectorAll('input, select, textarea'); clonedInputs.forEach(function(clonedInput, index) { clonedInput.addEventListener('input', function() { originalInputs[index].value = clonedInput.value; }); }); // Настраиваем передачу данных для чекбоксов var originalCheckboxes = customerDetails.querySelectorAll('input[type="checkbox"]'); var clonedCheckboxes = clonedDetails.querySelectorAll('input[type="checkbox"]'); clonedCheckboxes.forEach(function(clonedCheckbox, index) { clonedCheckbox.addEventListener('change', function() { originalCheckboxes[index].checked = clonedCheckbox.checked; // Для чекбокса "Соглашаюсь с правилами сервиса" if (clonedCheckbox.id === 'billing_agreement_check') { var originalContainer = originalCheckboxes[index].closest('.form-row'); var clonedContainer = clonedCheckbox.closest('.form-row'); if (clonedCheckbox.checked) { originalContainer.classList.remove('woocommerce-invalid'); originalContainer.classList.remove('woocommerce-invalid-required-field'); originalContainer.classList.add('woocommerce-validated'); clonedContainer.classList.remove('woocommerce-invalid'); clonedContainer.classList.remove('woocommerce-invalid-required-field'); clonedContainer.classList.add('woocommerce-validated'); } else { originalContainer.classList.remove('woocommerce-validated'); originalContainer.classList.add('woocommerce-invalid'); originalContainer.classList.add('woocommerce-invalid-required-field'); clonedContainer.classList.remove('woocommerce-validated'); clonedContainer.classList.add('woocommerce-invalid'); clonedContainer.classList.add('woocommerce-invalid-required-field'); } } }); }); } }); </script> |
1 2 3 4 5 6 7 8 9 10 |
## Если корзина не пустая - перенаправляем на Оформление заказа function redirect_cart_to_checkout() { if (is_cart() && !WC()->cart->is_empty()) { wp_safe_redirect(wc_get_checkout_url()); exit; } } add_action('template_redirect', 'redirect_cart_to_checkout'); |