Тема: Логика работы корзины

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

2

Re: Логика работы корзины

Логика работы корзины следующая:

Когда пользователь неавторизован:
- Товары попадают в БД и связаны по session_id
(логика видна в методе \Shop\Model\Cart::__construct)

Когда пользователь авторизовывается и у него есть товары в корзине:
- Товары, которые были привязаны  user_id до этого удаляются (т.к. пользователь собрал новую корзину)
- Новые товары дополнительно привязываются к user_id

Когда пользователь авторизовывается и у него нет товаров в корзине
- Товары, которые были привязаны к user_id привязываются к session_id
(т.е. пользователь видит товары, которые он собирал будучи авторизованным, например, на другом компьютере)

(логика трансформаций при авторизации видна в \Shop\Config\Handlers::userAuth)

Когда пользователь авторизован:
- Товары попадают в БД и у них проставляются session_id, user_id

------------------------------------

Выборка товаров в корзину из БД ведется всегда по session_id. (user_id - это дополнительный идентификатор, который позволяет производить манипуляции по перепривязке товаров при авторизации)

Теоретически, корзина может пропадать у пользователей, только если наступает завершение сессии, т.е. происходит смена session_id, т.е. пауза между действиями пользователя на сайте превышает настройку session.gc_maxlifetime в php.ini

Повысить оценку +1 Понизить оценку

Re: Логика работы корзины

Спасибо за ответ!

admin пишет:

Когда пользователь авторизовывается и у него есть товары в корзине:
- Товары, которые были привязаны  user_id до этого удаляются (т.к. пользователь собрал новую корзину)

Здесь не совсем понял про удаление.

4

Re: Логика работы корзины

- Товары, которые были привязаны  user_id до этого удаляются (т.к. пользователь собрал новую корзину)

Здесь описывается следующая ситуация:

- Допустим пользователь будучи авторизованным на одном компьютере (А) добавил в корзину несколько товаров и закрыл браузер. (товары привязались к его session_id и user_id)

- Затем он перешел на другой компьютер (Б) и будучи неавторизованным собрал новую корзину.

Встает вопрос: "Что делать, если пользователь авторизуется на компьютере Б с собранной новой корзиной?"

Единственно верный в данном случае вариант, удалить из базы товары, собранные на компьютере А и привязать новые товары к user_id, собранные на компьютере Б.

Повысить оценку Понизить оценку

Re: Логика работы корзины

Спасибо за пояснение!

6 Отредактировано Ярослав (12.05.2016 00:01:32)

Re: Логика работы корзины

Возможно я разобрался с пропадающими корзинами. Все дело в привязке элементов корзины к сессии у авторизованных пользователей.
1. В одном браузере авторизованный пользователь набрал корзину.
2. Зашел в другом браузере (например, дома). Элементы корзины перепривязываются при авторизации ко второй сессии, но в другом то браузере пользователь не выходил! В результате в первой сессии пользователь теряет корзину. 

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


Только что провел эксперимент:
1. Набрал в разных сессиях авторизованным пользователем корзины.
2. В сессии 1 вышел. (при этом корзина сохраняется и видна)
3. Сразу же авторизовался в сессии 1
4. В сессии 2 корзина сразу опустела.


Проверил у крупных магазинов логику:
1. Добавленный товар с разных авторизованных сессий  виден в корзине у обоих. Корзина общая, привязана к авторизованному пользователю или к сессии у гостя.
2. Если авторизоваться с заполненными корзинами, то содержимое корзин объединяется, а не заменяется новой как у нас.

7

Re: Логика работы корзины

Под одним и тем же логином заходят разные менеджеры и перехватывают друг у друга корзины.

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

Так как привязка товаров идет к session_id, то безусловно в вашем случае товары будут привязываться либо к одному пользователю, либо к другому, если они оба сидят за разными компьютерами под одной учетной записью. (так как у менеджеров будет разный session_id и общий user_id)

Повысить оценку Понизить оценку

8 Отредактировано Ярослав (12.05.2016 18:01:20)

Re: Логика работы корзины

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

Подавляющее число оптовиков - ИПшники без работников. И они в связи своей мобильностью как раз и чаще всего попадают с удаленным заказом.

Достаточно ли правки модели корзины,чтоб для авторизованных пользователей не использовать session_id? Или где то еще используется привязка?

9 Отредактировано Ярослав (12.05.2016 20:57:37)

Re: Логика работы корзины

Убрал удаление элементов корзины в handlers.inc.
Доработал модель корзины. Работал топором, буду тестировать:

 /**
    * Получать экземпляр класса можно только через ::currentBasket()
    */
    protected function __construct($mode = self::MODE_SESSION, Orm\Order $order = null)
    {
        $this->session_id = session_id();
        $this->mode = $mode;
        $this->order = $order;
        switch($this->mode) {
            case self::MODE_ORDER: {
                $this->cartitem = new Orm\OrderItem();
                //2016_05 для привязки корзины к пользователю
                $this->select_expression =array('order_id="#order_id1"',array(
                    'order_id1' => $this->order['id']
                ));
                $this->order_expression = 'sortn';
                break;
            }
            case self::MODE_EMPTY: {
                $this->cartitem = new Orm\CartItem();
            }
            default: {
                $this->cartitem = new Orm\CartItem();
                 //2016_05 ТУТ
                $this->select_expression = array('site_id="#site_id1" and (session_id="#session_id1" or (user_id="#user_id1" and user_id>0))',array(
                    'site_id1' => \RS\Site\Manager::getSiteId(),
                    'session_id1' => $this->session_id ,
                    'user_id1' => \RS\Application\Auth::getCurrentUser()->id
                 )   
                );                
                $this->order_expression = 'dateof';
            }
        }
        
        $this->loadCart();
    }

/**
    * Загружает корзину из базы данных
    * 
    * @return void
    */
    function loadCart()
    {
        $q = \RS\Orm\Request::make()
            ->from($this->cartitem)
            ->where($this->select_expression[0],$this->select_expression[1])//ТУТ
            
       $this->items = $q->objects(null, 'uniq');
       if ($this->mode == self::MODE_ORDER) {
           $this->order_items = $this->items;
       }
    }
 /**
    * Удаляет позицию из корзины.
    * 
    * @param string $uniq - Уникальный идентификатор элемента корзины
    * @return bool
    */
    function removeItem($uniq)
    {
        if (isset($this->items[$uniq])) {
            if ($this->mode == self::MODE_SESSION) {
                \RS\Orm\Request::make()
                    ->delete()
                    ->from($this->cartitem)
                   ->where($this->select_expression[0],$this->select_expression[1]) //ТУТ
                    ->where(array(
                        'uniq' => $uniq
                    ))->exec();
            }
            
            unset($this->items[$uniq]);
            unset($this->order_items[$uniq]);
            unset($this->cache_products[$uniq]);
            unset($this->cache_coupons[$uniq]);
        }
        return true;
    }

 /**
    * Очищает корзину
    */
    function clean()
    {
        $this->items = array();
        $this->order_items = array();
        $cache_coupons = null;
        $cache_products = null;
        
        $result = \RS\Orm\Request::make()
            ->delete()
            ->from($this->cartitem)
            ->where(
                 //2016_05_12 eventus поддержка привязки к пользователям
                  'site_id="#site_id1" and (session_id="#session_id1" or (user_id="#user_id1" and user_id>0))',array(
                    'site_id1' => \RS\Site\Manager::getSiteId(),
                    'session_id1' => $this->session_id ,
                    'user_id1' => \RS\Application\Auth::getCurrentUser()->id
                 ))->exec();
        
        $this->cleanInfoCache();
        return true;
    }
   /**
    * Возвращает информацию по количеству товаров и стоимости товаров в корзине
    * 
    * @param mixed $format - форматировать общую сумму заказа
    * @param mixed $in_base_currency - возвращать в базовой валюте
    * @return array
    */
    public static function getCurrentInfo($format = true, $use_currency = true)
    {
           self::currentCart()->cleanInfoCache();     //ТУТ добавил для принудительного обновления инф-ции о корзине 
        $options = (int)$format.(int)$use_currency.\Catalog\Model\CurrencyApi::getCurrentCurrency()->id;
        
        if (!isset($_SESSION[self::CART_SESSION_VAR][$options])) {
            self::currentCart()->getCartData($format, $use_currency);
        }
        
        return $_SESSION[self::CART_SESSION_VAR][$options];
    }
      

Итого:
1. если были товары в корзине при авторизации, то они попадут к в корзину авторизованному.
2. Любые изменения в корзине на разных устройствах под одним и тем же пользователем синхронизированы

10

Re: Логика работы корзины

Признаюсь, у меня на этот счет другое мнение, меня наоборот ставит в ступор, если я собрал корзину, авторизовался и в моей корзине вдруг появляются неожиданно "левые" товары (которые я когда-то добавлял с какого-то устройства где-то). Я же собрал абсолютно новую корзину сейчас!

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

Безусловно, вы можете в своем проекте поправить логику, как это вам нужно.
Выборка элементов корзины по session_id - есть только в классе \Shop\Model\Orm\Cart
Логика действий при авторизации есть только в \Shop\Config\Handlers::authUser

Повысить оценку Понизить оценку

11

Re: Логика работы корзины

Я и моя семья сейчас практически большинство покупок (кроме еды, наверное) делают через интернет. Дешевле, больше выбор. И достаточно часто пользуешься разными устройствами.
У 003, oзон, ситилинк, ибей, элиэкспресс, Днс, Вайлдберрис всегда корзина доступна везде (специально проверил).  Они стараются, чтобы товар, заинтересовавший пользователя, был постоянно на виду.

Изменил, как описал выше. Наблюдаю.

12

Re: Логика работы корзины

Я понял вашу точку зрения.

Полностью кросс-устройственной у нас будет функция Избранное (в будущих версиях), именно эта функция позволит добавив товар на одном устройстве видеть его на всех других устройствах абсолютно всегда. А уже с избранного всегда можно будет перенести товар в локальную корзину.

Повысить оценку +2 Понизить оценку

13

Re: Логика работы корзины

admin пишет:

Я понял вашу точку зрения.

Полностью кросс-устройственной у нас будет функция Избранное (в будущих версиях), именно эта функция позволит добавив товар на одном устройстве видеть его на всех других устройствах абсолютно всегда. А уже с избранного всегда можно будет перенести товар в локальную корзину.

Вот это нам было тоже очень полезно и удобно

Повысить оценку Понизить оценку

14

Re: Логика работы корзины

Отлично! Избранного не хватает.

15

Re: Логика работы корзины

А я Ярослава поддержу, меня как опт покупателя раздражало у некоторых поставщиков, что корзина с другого устройства недоступна! Лучше делать привязку по session_id, если юзер не авторизован, а если авторизован, то по user_id
Это и рознице не помешает и опту плюс.

Повысить оценку Понизить оценку

Re: Логика работы корзины

Всё будет, не переживайте.