ashtray 14 апреля 2014 0 3
Добрый день всем участникам клуба.
Использую сборку ShopModxBox для своего проекта. Разбираюсь с нуля, очень помогли вебинары Fi1osof-а.
Столкнулся с проблемой добавления нескольких товаров в корзину с 1 кнопки.
Поясню: есть 1 основной товар и к нему можно выбрать опции — товары из другой категории (грубо говоря отметить галочками). Нужно чтобы при нажатии кнопки «Далее» в корзину добавился как основной товар, так и выбранные опции, и произошел бы переход в корзину для оформления.
С одним товаром проблем нет.
Кнопку кидаю в форму с полями:

<input type="hidden" name="product_id" value="{$object.product_id}"/>
<input type="hidden" name="action" value="add_product"/>

И все отлично добавляется. А как добавить одновременно несколько товаров? Где написать цикл добавления? Или можно как-то поменять плагин корзины?
Вот ссылка на форму: форма выбора опций...
3 комментария
Boleg21
Boleg2 14 апреля 2014г в 22:04 #
Сам процессор корзины лежит тут, если не ошибаюсь:
Filesystem/Core/components/basket/processors/basket/mgr/orders/products/getdata.class.php

Его на финальной стадии расширяет следующий процессор:
Filesystem/Core/components/basket/processors/basket/web/orders/products/getdata.class.php

И всё это упирается в итоге в smarty-шаблоны вывода корзины.
Редактировать, полагаю, надо mgr-процессор, расширяющий базовый процессор getdata.
Сам с xPDO не работал, тут не помогу.
Если где ошибся — гуру, поправьте = ) Но хоть направление для изысканий задам.
Кстати, если еще не взято на вооружение — в редактировании очень помогает ModxSDK из репозитория Fi1osof, очень уж классный там редактор кода = )
a
ashtray 14 апреля 2014г в 22:50 #
Так это процессоры для вывода содержимого корзины, мне же надо добавить в корзину несколько товаров с 1 нажатия. Я так понимаю, что это процессор add.class.php и все с ним связанные. Как оно работает до меня немного не доходит — особенно в связке с ajax.

А что касается MODxSDK — действительно очень удобная вещь, я теперь в нем только и работаю, благодаря вебинарам Fi1osof-а
Tramp13571
Tramp1357 14 апреля 2014г в 22:41 #
за добавление товаров отвечает процессор web/orders/products/add.class.php, namespace basket.
на самом деле, можно и javascript цикл сделать, с последовательным добавлением нескольких товаров, через ajax, нужно только при формировании формы прописать в нее коды сопутствующих товаров и их количества.

Вообще, если эти товары добавляются по умолчанию, то проще тогда оформить набор как самостоятельный товар и не греть голову.
a
ashtray 14 апреля 2014г в 22:54 #
можно и javascript цикл сделать, с последовательным добавлением нескольких товаров, через ajax
.
Можно этот момент поподробнее описать. Я вот в упор не понимаю, как там оно с помощью ajax обрабатывается (товар в корзину добавляется).
Набор опций к каждому товару индивидуален и галочек может как не быть вовсе, так и отмечены могут быть все покупателем.
Tramp13571
Tramp1357 14 апреля 2014г в 23:07 #
когда давишь на submit, форма отправляет get или post — запрос. можно перехватить это нажатие, пройтись по форме и по каждому из выбранных товаров (чей чекбокс включен) сформировать отдельный ajax-запрос. т.е. на сервер не один запрос уйдет, а несколько. Посмотри, по какому адресу уходит запрос при добавлении одного товара, составляющие запроса и просто в цикле повторяешь столько раз, сколько надо.
a
ashtray 14 апреля 2014г в 23:22 #
В ajax не силен, посему вопросы.
Как смотреть по какому адресу уходит запрос? В форме для добавления одного товара action=""
Как перехватить нажатие submit. По событию onsubmit или onclick?
Tramp13571
Tramp1357 15 апреля 2014г в 00:15 #
по ajax: есть удобный компонент для форм malsup.com/jquery/form/
а где посмотреть — в окне дебаггера (есть и в FireFox и в chrome)

т.е. при добавлении передается action=products/add, product_id и quantity. вот это и надо в запросах кидать, меняться только последние 2 параметра будут. А как сделать цикл — тут я не силен, javascript пока сам грызу по мануалам :(
a
ashtray 15 апреля 2014г в 02:39 #
Спасибо за подсказку, сделал все при помощи ajax запроса к коннектору напрямую:
<script>
    $(function()
    { $('#product_f').submit(function(e){
        //отменяем стандартное действие при отправке формы 
        e.preventDefault(); 
        //берем из формы метод передачи данных 
        var m_method=$(this).attr('method'); 
        //получаем адрес скрипта на сервере, куда нужно отправить форму 
        var m_action='http://www.tehnofazenda.ru/assets/components/basket/connectors/connector.php?action=products/add'; 
        {assign var=arr value=array(1,2,3,4)}
        {foreach from=$arr item=i}
    
        var op_data="product_id={$object{$i}.product_id}";
        if (document.getElementById('option{$link{$i}}').checked)
            {
              $.ajax({ 
              type: m_method, 
              url: m_action, 
              data: op_data, 
              success: function(result){ 
                     } 
                 });
            }
        {/foreach}
        //получаем данные, введенные пользователем в формате input1=value1&input2=value2..., 
        //то есть в стандартном формате передачи данных формы 
        var m_data=$(this).serialize(); 
        $.ajax({ 
            type: m_method, 
            url: m_action, 
            data: m_data, 
            success: function(result){ 
                setTimeout("document.location.href='http://www.tehnofazenda.ru/order/'", 700);
                } 
            });
        }); 
    });
</script>
Tramp13571
Tramp1357 15 апреля 2014г в 02:44 #
Рад, что помог.
Да, примерно так. только неплохо в ajax error обрабатывать и при ошибке давать команду на удаление уже добавленных в этой транзакции товаров.
А может, и не надо :)
Fi1osof1
Fi1osof 17 апреля 2014г в 17:34 #
Добрый день!

Извиняюсь за долгий ответ, был в отъезде на несколько дней.

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

Ну да ладно, это потом, а пока просто еще более детально разберем еще один вариант реализации этой задачи, потому что тайминги в JS — это не совсем круто, да и прочие моменты есть. Вам на самом деле просто надо переопределить action-процессор и в нем реализовать циклическое выполнение процессора добавления товара. Как это делается, написано здесь (читайте внимательно раздел «Переопределяем процессоры»).
В кастомном action-процессоре укажите свой отдельный процессор, в методе process которого и пропишите примерно следующее:
public function process(){
    $path = $this->modx->getObject('modNamespace', 'basket')->getCorePath().'processors/';
    
    foreach($products as $product_id => $quantity){
        
        if(!$response = $modx->runProcessor('basket/web/orders/products/add',
        array(
            "product_id"    => $product_id,
            "quantity"      => $quantity ? $quantity : 1,
        ), array(
            'processors_path' => $path,
        ))){
            return $this->failure("Не удалось выполнить процессор");
        }
        
        // else
        if($response->isError()){
            return $response->getResponse();
        }
    }

    return $this->success('Товары успешно добавлены');
}


Тут конечно могут быть логические ошибки с обработчиком ошибок (к примеру, из пяти товаров 3 добавилось, а с четвертым ошибка, и он вернет ошибку, хотя три все-таки будут добавлены), но это крайне мелкая вероятность, так что можно пренебречь. И именно поэтому и надо ядро доработать. Но в целом это вполне рабочий вариант, и выполнено будет в один запрос, после чего корректно на сервер уйдет запрос на состояние корзины.

P.S. Спасибо за положительные отзывы :)
Авторизуйтесь или зарегистрируйтесь (можно через соцсети ), чтобы оставлять комментарии.