Что вам понадобится?
- Руки и голова
- Немного терпения, чтобы дочитать этот гайд.
- От 5 минут времени на программирование.
- Элементарные основы PHP.
- Сайт на основе 220+
Вместо введения
Для простоты масштабирования возможностей корзины все расширения для JBZoo, вне зависимости чем они занимаются, организованы одинаково. Проще говоря, все это элементы. Разница между элементом скидки или валидатором будет лишь в одном методе, который отвечает за валидацию или за изменение общей суммы заказа.
Поэтому, если вы научитесь писать один вид элементов, то другие написать будет в разы проще. Все работает по аналогии.
Как было заявлено в начале статьи, мы будем разбирать как написать свой элемент скидки.
Где находится элемент?
Все элемент лежат в этой папке /media/zoo/applications/jbuniversal/cart-elements
Они строго разделены по папкам-типам (своему предназначению). Т.к. нас интересует скидка, то смотрим одну из папок
- modifieritemprice - скидка на определенный товар или группу (до добавления в корзину)
- modifierorderprice - скидка применяется на весь заказ сразу после вычисления предварительной суммы.
Анатомия элемента или из чего он состоит?
Минимальный набор для любого элемента - это...
- element.xml файл, который описывает набор настроек и добавляет мета информацию (название, автора, версию).
- element.php файл, который по сути и реализует всю логику элемента
Остальное содержимое папки элемента - опциональное
- assets - статическое содержимое для элемента, т.е JavaScript, CSS и картинки
- tmpl - папка с шаблонами элемента
- language - место хранения локализация для элемента
Иногда бывают другие файлы и папки, но это уже особенности конкретного элемента.
Именование в элементе
Допустим наш элемент будет называться MyDiscount, тогда будет удобно использовать псевдоним (алиас) mydiscount.
Это важное слово, которое обязательно указать в разных местах элемента, иначе система его не сможет найти.
Создаем два новых файла
/cart-elements/modifierorderprice/ mydiscount / mydiscount.php
/cart-elements/modifierorderprice/ mydiscount / mydiscount.xml
Открываем php файл, добавляем туда код
class JBCartElementModifierOrderPriceMydiscount extends JBCartElementModifierOrderPrice { }Обратите внимание, что имя класса составное JBCartElement + ModifierOrderPrice + Mydiscount . Регистр именования класса нас не сильно волнует.
В xml добавляем типичный набор мета данных. Настройки обсудим позже
<?xml version="1.0" encoding="utf-8"?> <element type="element" group="Core" hidden="false"> <name>My Discount</name> <author>SmetDenis</author> <creationDate>2015</creationDate> <copyright>Copyright (C) JBZoo.com</copyright> <authorEmail>denis@jbzoo.com</authorEmail> <authorUrl>http://jbzoo.com</authorUrl> <version>1.0</version> <description>Simple example</description> </element>
Как работает любая скидка в JBZoo 220?
Вся работа элемента сводится к работе одного метода getRate(). Его задача вернуть положительно (для наценки) или отрицательное(для скидки) число, которое затем будет добавлено к обрабатываемой сумме (товара или всего заказа).
Допустим, мы хотим добавить скидку в 10% если сумма за все товары больше 2000 рублей.
public function getRate() { $orderSum = $this->_order->getTotalForItems(); // получили сумму за все товары (без доставки и прочего) $discount = 0; if ($orderSum->compare('2000rub', '>=')) { // сравниваем c 2000 рублей $discount = '10%'; // скидка, если сумма больше } return $this->_order->val($discount)->negative(); // обязательно вернуть объект и добавляем знак минус (чтобы была скидка) }
Как видите, все довольно просто. Единственный вопрос. который может у вас тут появиться, почему мы не работаем с нормальными числами а с объектом.
Дело в том, что от товара до создания заказа сумма (так что, к оплате) может претерпевать огромное количество изменений. На вскидку,
- товар стоит 100 грн.
- добавляем его в корзину 5 шт (500грн)
- добавляем другой товар в 100 руб, 4 штуки
- срабатывает модификатор скидки для второго товара если кол-во больше 3-х (-10%)
- человек в корзине указывать промо код (-15% ко всему заказу)
- вычисляется сумма доставки через "Новую почту" (+58 грн).
- клиент оплачивает через PayPal в долларах по курсу сайта
Получаем примерную форуму (на пальцах)
Сумма заказа = (((100uah * 5) + ((100rub * 4) - 10%) - 15%) + 58uah ) => usd
Если развернуть все вычисления, то получим огромную портянку кода, где добрая доля - это вызова конвертирования валюты и вычисления процентов. Всю эту реализацию скрывает объект JBCartValue. Он очень важен в работе сайта, целиком и полностью зависит от настроек валюты. Поэтому мы акцентируем на них большое внимание.
Добавляем элементу параметры
Чтобы каждый раз не лезть в код, добавим 2 параметра в элемент - лимит и размер скидки.
Т.е при достижении лимита - сработает скидка.
Для этого в XML объявляем блок params и добавляем туда две строки. Особое внимание обратите на name, по нему мы будем обращаться в коде.
<params> <param name="rate" type="text" default="10%" label="Discount"/> <param name="limit" type="text" default="10000" label="Limit"/> </params>Чтобы получить доступ к сохраненным параметрами используем объект config внутри элемента
$rate = $this->config->get('rate', '20%'); // здесь 20 - это значение по умолчаниюПочти "волшебный" объект суммы JBCartValue
Как вы уже поняли, для работы с суммами мы активно используем объект JBCartValue, который скрывает внутри себя все вычисления. Возможностей у объекта огромное количество, желающие могут посмотреть его реализацию тут
media\zoo\applications\jbuniversal\framework\classes\cart\jbvalue.php
Я не будут перечислять все (оставлю на внеклассное чтение), только акцентирую внимание на самом важном
Создание объекта. Есть два разных варианта и они зависят от того создан ли заказ или еще нет.
Дело в том, что после создания заказа (он уже сохранен в базе), информация о курсах валюты копируется и сохраняется в заказ. Таким образом, если курс подскочит, на конечный заказ это не повлияет.
<?php $sum = JBCart::val(); // нулевая сумма, на основе текущих валют $order->val(); // нулевая сумма, валюты из конкретного заказа $this->_order->val(); // тоже самое, обращение из элемента скидки, т.е $this - это объект элемента
Если заказ еще не создан (т.е еще находится в сессии), то для объекта берутся текущие валюты. С этим думаю понятно. Поехали дальше.
Другие примеры создания объекта суммы
// 10 единиц в валюте по умолчанию $sum = JBCart::val(10); // 10 единиц в конкретной валюте $sum = JBCart::val(10, 'usd'); $sum = JBCart::val('10rub'); $sum = JBCart::val(aray('10', 'UAH')); // встроенный парсер сам разберется что мы от него хотим (уберет пробелы, разберется с запятыми) $sum = JBCart::val('-50,6 eur'); $sum = JBCart::val('-50.6eur'); $sum = JBCart::val(' - 5 0 . 6 eur '); $sum = JBCart::val(' + 5 0 , 6 % '); // и даже проценты $sum = JBCart::val('-15%');Как сравнить две цены
$val1 = JBCart::val('55usd'); $val2 = JBCart::val('55eur'); if ($val1->compare($val2, '<=')) { // проверка 55usd <= 55eur } if ($val1->compare('100 uah', '=')) { // 55usd == 100uah }Как изменить сумму
$val1 = JBCart::val('10usd'); $val2 = JBCart::val('1eur'); $val1->add($val2); // после этого в val1 будет хранится чуть больше 11 долларов в валюте "доллар" $val2->add($val1); // после этого в val2 будет хранится чуть больше 11 долларов в валюте "евро" $val2->add('-10rub'); // отнимаем 10 рублей от 1 евро $val2->minus('10%'); // скидка 10% от 1 евроРендеринг
$val = JBCart::val('20', 'usd'); echo $val->noStyle() . '<br>'; // без стиля (округление и форматирование не применяется) echo $val->val() . '<br>'; // просто текущее значение без валюты echo $val->plain() . '<br>'; // другой текстовый вывод, echo $val->html() . '<br>'; // полный вариант для JS и со всеми стилями echo $val->text() . '<br>'; // html с обработкой strip_tags // в любой метод можно передать валюту, чтобы без конвертирования (состояние объекта не изменится) // вывести число в другой валюте echo $val->html('RUB');Конвертирование (не советую без срочной необходимости)
$val = JBCart::val('10usd'); $val->val(); // значение в долларах $val->convert('rub'); $val->val(); // значение в рубляхОтладка (включите режим отладки Joomla)
$val = JBCart::val('10usd'); $val->dump(); // чистейшее состояние объекта без форматирования, округления и стилей $val->logs(); // история изменений объектаВсе и сразу
$value = JBCart::val('10 eur')->debug(1); dump($value->text(), 0, 'before add'); $value ->convert('rub') ->add('10%') ->add('-5 rub') ->minus(array('-5', 'rub')) ->minus(array('5', 'rub')) ->multiply(9) ->abs() ->negative() ->invert() ->positive() ->invert() ->setFormat(array('num_decimals' => -2), 'rub') ->add(500); dump($value->logs(), 0); dump($value->dump(), 0, 'after add');Простейший элемент
Объединяем все накопленные знания и делаем скидку 10% для заказа где сумма больше 100 000 рублей.
Настройки
Элемент в действии
Архив с элементом можно найти в нашем маркете - http://forum.jbzoo.c...delennoj-summy/
Версии
Тестировал на JBZoo 2.2.0 rev2778, Zoo 3.3.4, Joomla 3.4.1
PS Топик будет дописываться по мере спроса, в скором времени появится в общей документации.