Сохранение корзины для пользователей

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

В качестве решения получился очень простой плагин, который выполняет 2 действия:
1) Сохраняет содержимое корзины в extended поля пользователя после каждого изменения корзины
2) Восстанавливает содержимое корзины перед каждой обработкой запрошенной страницы.


Возможно, появится вопрос, почему реальная корзина переписывается при каждой обработке страницы и почему нельзя это сделать только при авторизации?
В качестве ответа ситуация:
1) На одном компьютере пользователь добавил капкейк и торт
2) На втором компьютере удалил торт и добавил макаруны
3) При возвращении на первый ПК в корзине окажутся капкейк и макаруны

По коду плагина понятно, какие события нужно активировать в его свойствах.

<?php
switch($modx->event->name) {
    case 'msOnAddToCart':
    case 'msOnChangeInCart':
    case 'msOnEmptyCart':
    case 'msOnRemoveFromCart':
        if ($user = $modx->getAuthenticatedUser('web') and $ms2 = $modx->getService('minishop2')) {
            $ms2->initialize($modx->context->key);
            $profile = $user->getOne('Profile');
            $extended = $profile->get('extended');
            $extended['ms2cart'] = $ms2->cart->get();
            $profile->set('extended', $extended);
            $profile->save();
        }
        break;
        
    case 'OnWebPageInit':
    case 'OnWebLogin':
        if ( $user = $modx->getAuthenticatedUser('web') and  $ms2 = $modx->getService('minishop2')) {
            $ms2->initialize($modx->context->key);
            $profile = $user->getOne('Profile');
            $extended = $profile->get('extended');
            if ( isset($extended['ms2cart']) && !empty($extended['ms2cart']) ) {
                $ms2->cart->set($extended['ms2cart']);
            }
        }
        break;
}

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

Оформлять пакет из такого плагина бессмысленно, но если в комментариях идея будет поддержана и развита, возможно появление более функционального варианта в виде компонента.
Воеводский Михаил
08 августа 2016, 15:06
modx.pro
42
5 734
+12

Комментарии: 13

Илья Уткин
08 августа 2016, 18:23
1
+1
По-моему, очень нужная вещь. У меня жена только так делает заказы — на мобильном телефоне добавляет всё, что нужно в корзину, потом лишнее убирает, а уже оформляет заказ через компьютер — так удобнее вводить адрес и данные.
    Воеводский Михаил
    08 августа 2016, 18:27
    0
    Илья, предлагай расширение функционала :)
      Илья Уткин
      08 августа 2016, 18:34
      +1
      Нужно сохранять эти корзины в базе данных, с возможностью их просмотра из админки. Но вообще, есть дополнение ordersUnformed. Лучше было бы как-то связаться с автором и предложить внедрить в дополнение функционал восстановления корзин для пользователей. Или делать дублирующее дополнение, но с расширенным функционалом.
Evgeny Epifanov
08 августа 2016, 22:11
+1
Очень полезный плагин.
В качестве расширения функционала:
— отправлять посетителю на почту письмо с содержимым корзины в автоматическом или ручном режиме.
    lexikon
    22 ноября 2016, 12:10
    1
    0
    есть небольшая проблема в логике!
    Если мы формируем заказ будучи не авторизованными, а потом авторизовываемся на странице оформления заказа, то корзина заменяется и мы теряем товары, которые только что сложили.
    Для исправления необходимо чуть поправить событие OnWebLogin
    case 'OnWebLogin':
            if ( $user = $modx->getAuthenticatedUser('web') and  $ms2 = $modx->getService('minishop2')) {
                $ms2->initialize($modx->context->key);
                $profile = $user->getOne('Profile');
                $extended = $profile->get('extended');
                if ( isset($extended['ms2cart']) && !empty($extended['ms2cart']) ) {
                    $currentcart = $ms2->cart->get();
                    $cart = array_merge($currentcart, $extended['ms2cart']);
                    $ms2->cart->set($cart);
                }
            }
            break;
      Воеводский Михаил
      22 ноября 2016, 12:17
      0
      Тоже нельзя сказать, что это идеальное решение. Все зависит от конкретного случая. Потому пусть будут оба варианта, а разработчики сами для себя выберут подходящий.
        lexikon
        22 ноября 2016, 12:21
        0
        так и есть, только индивидуально… в моем случае есть возможность авторизоваться непосредственно на странице оформления для того, чтобы заполнить все поля за пользователя, а тут получается заподлянка какая-то(сложил одно, а в заказ упало другое)

        Хорошим решением будет отличать устройства, если же устройства одни и те же — то корзину не восстанавливать! Иначе восстановить.
          lexikon
          03 декабря 2016, 11:40
          0
          Тут столкнулся с проблемой, msPromoCode не работает с данным решением, вообще хрень полная происходит, концов не найти) походу по событию msOnChangeInCart перезаписывает данные, которые уже обновлены.
            Воеводский Михаил
            03 декабря 2016, 23:02
            0
            Данное решение является лишь направлением для мысли и, естественно, легко может конфликтовать с любыми похожими алгоритмами. В качестве решения попробуйте изменит приоритеты плагинов. Если не поможет, придется самостоятельно вникать в суть конфликта.
        Sergey (Sentinel)
        26 марта 2019, 20:53
        0
        Подскажите, как сделать условие для msOptionsPrice2? А то фасовки сбиваются…
          Воеводский Михаил
          27 марта 2019, 21:19
          0
          Смотреть, что хранит в сессии msOptionsPrice, сохранять и восстанавливать эти данные вместе с корзиной.
          Lori
          30 ноября 2020, 13:42
          0
          У меня для авторизации используется Login. Создал плагин, отметил события, но что-то ничего не сохраняется.
            Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
            13