ShopKeeper, сохраняем сессию с товарам в базе. Чтобы корзина не отчищалась.

Итак, для чего это нужно?
Много работаю с ШК, и много приходится допиливать всяких мелочей.
Представляю на Ваш суд плагин для сохранения сессии с товарами в БД, чтобы можно было продолжить наполнять корзину на следующий день, или когда захочется.
У меня заказчики оптовики, и там набирают по много позиций. Возможно для кого-то это тоже будет актуально.

Работает только для авторизованных пользователей сайта!

Для начала идем в PhpMyAdmin и создаем новое поле в таблице modx_web_users (у вас префикс может быть другой в базе).
Имя поля sksession, тип LONGTEXT (так как данных у меня например здесь бывает очень много).

Далее нам необходимо создать событие в ШК для плагина. Сам автор ШК рекомендует это делать.

Открываем class.shopkeeper.php и находим примерно строку 277, там должно быть
$_SESSION['addit_params'] = $addit_paramsStr;

и после этого добавляем
$evtOut = $this->modx->invokeEvent('OnSHKaddItem');


Теперь нам необходимо добавить в БД сайт это событие, выполняем следующий запрос в базу
INSERT INTO `modx_system_eventnames` VALUES (NULL, 'OnSHKaddItem', '6', 'Shopkeeper');
(повторюсь, что префикс у вас может быть другой, и надо будет исправить его на ваш.)
Далее создаем плагин SkSaveSession и ставим ему события OnSHKaddItem, OnSHKbeforeSendOrder, OnWebLogin
код плагина
$e = &$modx->Event;
$id = $modx->getLoginUserId();

if (($e->name == 'OnSHKaddItem')) {
$ses = $_SESSION['purchases'];
$addit = $_SESSION['addit_params'];
$res = $ses."|||".$addit;  
$modx->db->query( "UPDATE modx_web_users SET sksession='".$res."'  WHERE id='".$id."'");

}

if (($e->name == 'OnSHKbeforeSendOrder')) {
  $ses = '';
  $modx->db->query( "UPDATE modx_web_users SET sksession='".$ses."' WHERE id='".$id."'");

}

if (($e->name == 'OnWebLogin')) {

$query = $modx->db->query( "SELECT sksession FROM modx_web_users WHERE id='".$id."'");
$data = mysql_fetch_array($query);


if ($data['sksession']!='') 
{
  $res = explode("|||", $data['sksession']);
  $_SESSION['purchases']=$res[0];
  $_SESSION['addit_params']=$res[1];
}

}


Вот как бы и все. При каждом добавлении товара в корзину сессия пишется в базу. При отправке заказа база подчищается. При авторизации пользователя сессия принимает значение поля из базы.

П.С. Сильно не пинать, ибо в кодерстве не силен я :)

UPD 26.08.2013 исправил пару ошибок.

10 комментариев

avatar
А почему бы в кукисах не хранить? Проще и тоже можно сказать вечно. Я бы базу не захламлял сессиями
avatar
Судя по коду — вы всем пользователям пишете одинаковые корзины и стираете их у всех же при отправке любого заказа? Иначе, как объяснить отсутствие проверки по id пользователя при обновлении базы?

"UPDATE modx_web_users SET sksession='".$ses."'"
?
avatar
Согласен, косяк! Надо поправить.
avatar
Вот насколько полезно не стесняться своего кода и выкладывать для всех
сразу и баги поправят и ткнут носом где явно говнокод :)
вообщем одни плюсы )
еще и сообществу полезное решение:)
avatar
Ну да. Не сильно уверен также насчет $id пользователя — боюсь, если неавторизованный пользователь что-то закажет или добавит в корзину — то повалятся ошибки при попытке обновить запись в базе. Надо бы еще и тут проверку делать if($id)
avatar
Согласен. У меня просто заказы только авторизованные делают.
avatar
Хотел бы уточниться. Это решение, насколько я понимаю, для EVO? И насколько сильно оно будет отличаться в случае использования Shopkeeper в Revo?
avatar
Вариант для 1.3+
$e = &$modx->Event;
$id = $modx->getLoginUserId();


if (($e->name == 'OnSHKcalcTotalPrice') and $id != FALSE) {
    $modx->db->query("UPDATE " . $modx->getFullTableName('web_users') . " SET sksession='" . $_SESSION['purchases'] . "|||" . $_SESSION['addit_params'] . "'  WHERE id='" . $id . "'");
}

if (($e->name == 'OnSHKbeforeSendOrder') and $id != FALSE) {
    $modx->db->query("UPDATE " . $modx->getFullTableName('web_users') . " SET sksession='' WHERE id='" . $id . "'");
}

if (($e->name == 'OnWebLogin')) {
    $result = $modx->db->query("SELECT sksession FROM " . $modx->getFullTableName('web_users') . " WHERE id='" . $id . "'");
    while ($row = $modx->db->getRow($result)) {
        if ($row['sksession'] != '') {
            $res = explode("|||", $row['sksession']);
            $_SESSION['purchases'] = $res[0];
            $_SESSION['addit_params'] = $res[1];
        }
    }
}
Комментарий отредактирован 2017-08-27 23:17:40 пользователем trifle
avatar
Спасибо!
avatar
Доброго времени суток, столкнулся с той же проблемой, но на Revo, написал инструкици и выложил код тут. За основу брал этот код, благодарю что выложили!) Дописал там функционал чтобы если пользователь заполнил корзину, авторизируется, а унего в корзине уже были товары, они складываюлись вместе
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.