Генерация ссылки на корзину и восстановление корзины по ссылке.
Добрый день.
Давайте попрактикуемся с задачкой описанной в заголовке и за 10 минут напишем готовое бесплатное решение, без применения дополнительных компонентов.
Наш мини-компонент будет состоять из двух частей.
1. Сохранение собственной корзины и генерация ссылки на нее
2. Обработка ссылки при ее открытии и восстановление корзины.
Структурно компонент будет состоять из трех частей.
1. Класс компонента
2. Плагин
3. Js файл, который по сути нужен только для того чтобы отловить нажатие на кнопку «Получить ссылку» и показать готовую ссылку.
Начнем с того что, создадим в каталоге /core/components/ новый каталог с нашим компонентом. Назовем его например savecart
В каталоге компонента будет один единственный файл savecart.class.php
Обратите внимание обязательно только нижний регистр, и постфикс сlass. Такое правило написания требует MODX, для того, чтобы он мог найти файл при использовании метода $modx->getService(). А вот название класса уже можно писать как угодно.
Первоначальная структура файла такая:
Метод $modx->getService() автоматически передает в конструктор класса экземпляр $modx. Мы сохраняем ссылку на него, и можем использовать во внутренних методах все возможности MODX.
Мы знаем что корзина хранится в сессии, а именно в $_SESSION['minishop2']['cart'] так что достаточно сохранить этот массив куда-либо, а потом его извлечь и подсунуть обратно в сессию. Вот и вся теория.
Сохранять по разному. Я предлагаю использовать для этого кэш MODX. Если вы плаваете в этом вопросе, то очень рекомендую познакомиться с исчерпывающей статьей о сохранении пользовательских данных в кэш
@Сергей Шлоков Низкий поклон за хороший материал. До сих пор пользуюсь.
На самом деле все просто. пишем новый служебный метод для сохранения корзины в кэш. Всего несколько строчек. Обратите внимание. Я поставил спецификатор доступа private, так как это служебный метод. Он будет недоступен снаружи. Чтобы сохранить данные этот метод кто-то должен вызвать внутри класса.
Теперь создадим плагин saveCart. Привяжем к нему событие OnHandleRequest
Плагин также очень простой
Вот и все. С первой частью мы разобрались.
Давайте кратко повторим, что у нас получилось.
1. Вы при помощи js отлавливаете нажатие нужной кнопки и посылаете POST запрос с определенным экшеном. Надеюсь здесь пример не нужен.
2. Плагин ловит нужный экшен, подключает компонент и запрашивает ссылку.
3. Компонент сохраняет корзину из сессии в кэш, в качестве уникального ключа использует идентификатор сессии пользователя. Генерирует ссылку типа ?cart_id={session_id}
4. Возвращаем готовую ссылку обратно в js скрипт, который показывает ее на экране. Тут думаю тоже все понятно. Если нет напишите — покажу пример.
На сцене все те же.
1. Плагин на событие onHandleRequest
Всего несколько строк
2. Компонент и его метод восстановления корзины
Нам понадобится всего один метод в несколько строк
Полный код класса компонента (46 строк со всеми отступами)
Давайте попрактикуемся с задачкой описанной в заголовке и за 10 минут напишем готовое бесплатное решение, без применения дополнительных компонентов.
Наш мини-компонент будет состоять из двух частей.
1. Сохранение собственной корзины и генерация ссылки на нее
2. Обработка ссылки при ее открытии и восстановление корзины.
Структурно компонент будет состоять из трех частей.
1. Класс компонента
2. Плагин
3. Js файл, который по сути нужен только для того чтобы отловить нажатие на кнопку «Получить ссылку» и показать готовую ссылку.
Сохраняем корзину
Начнем с того что, создадим в каталоге /core/components/ новый каталог с нашим компонентом. Назовем его например savecart
В каталоге компонента будет один единственный файл savecart.class.php
Обратите внимание обязательно только нижний регистр, и постфикс сlass. Такое правило написания требует MODX, для того, чтобы он мог найти файл при использовании метода $modx->getService(). А вот название класса уже можно писать как угодно.
Первоначальная структура файла такая:
<?php
class SaveCart
{
public $modx;
public function __construct(modX $modx, array $config = array())
{
$this->modx = &$modx;
}
}
Метод $modx->getService() автоматически передает в конструктор класса экземпляр $modx. Мы сохраняем ссылку на него, и можем использовать во внутренних методах все возможности MODX.
Мы знаем что корзина хранится в сессии, а именно в $_SESSION['minishop2']['cart'] так что достаточно сохранить этот массив куда-либо, а потом его извлечь и подсунуть обратно в сессию. Вот и вся теория.
Сохранять по разному. Я предлагаю использовать для этого кэш MODX. Если вы плаваете в этом вопросе, то очень рекомендую познакомиться с исчерпывающей статьей о сохранении пользовательских данных в кэш
@Сергей Шлоков Низкий поклон за хороший материал. До сих пор пользуюсь.
На самом деле все просто. пишем новый служебный метод для сохранения корзины в кэш. Всего несколько строчек. Обратите внимание. Я поставил спецификатор доступа private, так как это служебный метод. Он будет недоступен снаружи. Чтобы сохранить данные этот метод кто-то должен вызвать внутри класса.
private function _saveUserCart()
{
//Получаем корзину из сессии
$cart = $_SESSION['minishop2']['cart'];
$savedCart = array(
'cart' => $cart
);
//Указываем каталог saved_cart в папке cache
$options = array(
xPDO::OPT_CACHE_KEY => 'saved_cart',
);
//Получаем уникальный идентификатор пользователя.
// Я использую тот, что генерирует MODX. Можно собрать свою рандомную строку
$id = session_id();
//Сохраняем, время хранения месяц.
$this->modx->cacheManager->set($id, $savedCart, 60 * 60 * 24 * 30, $options);
//Возвращаем уникальный идентификатор чтобы подсунуть его в ссылку
return $id;
}
Данные в кэш сохранены. Осталось сгенерировать и вернуть ссылку. Для этого пишу еще один метод. На этот раз публичный, доступный снаружи. Именно его мы будем вызвать в плагине. Он еще проще. public function getCartLink($page_id)
{
//Вызываем служебный метод сохранения корзины
$cart_id = $this->_saveUserCart();
//Возвращаем в плагин готовую ссылку
return $this->modx->makeUrl($page_id, 'web', ['cart_id' => $cart_id], 'full');
}
Половину работы сделали. Вот полный код того, что получилось. <?php
class SaveCart
{
public $modx;
public function __construct(modX $modx, array $config = array())
{
$this->modx = &$modx;
}
public function getCartLink($page_id)
{
$cart_id = $this->_saveUserCart();
return $this->modx->makeUrl($page_id, 'web', ['cart_id' => $cart_id], 'full');
}
private function _saveUserCart()
{
$cart = $_SESSION['minishop2']['cart'];
$savedCart = array(
'cart' => $cart
);
$options = array(
xPDO::OPT_CACHE_KEY => 'saved_cart',
);
$id = session_id();
$this->modx->cacheManager->set($id, $savedCart, 60 * 60 * 24 * 30, $options);
return $id;
}
}
Теперь создадим плагин saveCart. Привяжем к нему событие OnHandleRequest
Плагин также очень простой
switch ($modx->event->name) {
case 'OnHandleRequest':
// Js скрипт будет обращаться к сайту передавая конкретный action для идентификации
if (!empty($_POST['action']) && $_POST['action'] === 'getCartLink') {
//Загружаем свежесозданный компонент
$SaveCart = $modx->getService('SaveCart', 'savecart', MODX_CORE_PATH . 'components/savecart/');
//Дергаем генерацию ссылки
// передаем id страницы корзины
$cart_link = $SaveCart->getCartLink(5);
//Готовим json для ответа в JS
$output = [];
$output['success'] = true;
$output['link'] = $cart_link;
echo json_encode($output);
die();
}
break;
}
Вот и все. С первой частью мы разобрались.
Давайте кратко повторим, что у нас получилось.
1. Вы при помощи js отлавливаете нажатие нужной кнопки и посылаете POST запрос с определенным экшеном. Надеюсь здесь пример не нужен.
2. Плагин ловит нужный экшен, подключает компонент и запрашивает ссылку.
3. Компонент сохраняет корзину из сессии в кэш, в качестве уникального ключа использует идентификатор сессии пользователя. Генерирует ссылку типа ?cart_id={session_id}
4. Возвращаем готовую ссылку обратно в js скрипт, который показывает ее на экране. Тут думаю тоже все понятно. Если нет напишите — покажу пример.
Открываем ссылку и восстанавливаем корзину
На сцене все те же.
1. Плагин на событие onHandleRequest
Всего несколько строк
//Запускаем обработчик только если есть нужный GET параметр
if(!empty($_GET['cart_id'])){
//Фильтруем значение GET параметра
$cart_id = filter_input(INPUT_GET, 'cart_id', FILTER_SANITIZE_STRING);
//Подключаем компонент
$SaveCart = $modx->getService('SaveCart', 'savecart', MODX_CORE_PATH . 'components/savecart/');
// Вызываем нужный метод компонента.
$SaveCart->getSavedCart($cart_id);
}
Полный код плагина получился вот такой (23 строки с отступами)switch ($modx->event->name) {
case 'OnHandleRequest':
if (!empty($_POST['action']) && $_POST['action'] === 'getCartLink') {
$SaveCart = $modx->getService('SaveCart', 'savecart', MODX_CORE_PATH . 'components/savecart/');
$cart_link = $SaveCart->getCartLink(5);
$output = [];
$output['success'] = true;
$output['link'] = $cart_link;
echo json_encode($output);
die();
}
if(!empty($_GET['cart_id'])){
$cart_id = filter_input(INPUT_GET, 'cart_id', FILTER_SANITIZE_STRING);
$SaveCart = $modx->getService('SaveCart', 'savecart', MODX_CORE_PATH . 'components/savecart/');
$SaveCart->getSavedCart($cart_id);
}
break;
}
2. Компонент и его метод восстановления корзины
Нам понадобится всего один метод в несколько строк
//На входе получаем идентификатор сохраненной корзины
public function getSavedCart($cart_id)
{
//Забираем из кэша сохраненную корзину
$cart = $this->modx->cacheManager->get($cart_id, array(xPDO::OPT_CACHE_KEY => 'saved_cart'));
if (!empty($cart)) {
// Подсовываем ее в сессию минишопа
$_SESSION['minishop2']['cart'] = $cart['cart'];
}
}
Полный код класса компонента (46 строк со всеми отступами)
<?php
class SaveCart
{
public $modx;
public function __construct(modX $modx, array $config = array())
{
$this->modx = &$modx;
}
public function getCartLink()
{
$cart_id = $this->_saveUserCart();
return $this->modx->makeUrl(129, 'web', ['cart_id' => $cart_id], 'full');
}
public function getSavedCart($cart_id)
{
$cart = $this->modx->cacheManager->get($cart_id, array(xPDO::OPT_CACHE_KEY => 'saved_cart'));
if (!empty($cart)) {
$_SESSION['minishop2']['cart'] = $cart['cart'];
}
}
private function _saveUserCart()
{
$cart = $_SESSION['minishop2']['cart'];
$savedCart = array(
'cart' => $cart
);
$options = array(
xPDO::OPT_CACHE_KEY => 'saved_cart',
);
$id = session_id();
$this->modx->cacheManager->set($id, $savedCart, 60 * 60 * 24 * 30, $options);
return $id;
}
}
Поблагодарить автора
Отправить деньги
Комментарии: 6
Да уже давно же написано shareCart
Может быть. Не пользовался.
Моя задача была показать, что компонент для MODX это не обязательно долго-сложно.
Моя задача была показать, что компонент для MODX это не обязательно долго-сложно.
Дык твой компонент в базу пишет. А мой в кэш. Это в разы быстрее и проще.
При восстановлении желательно цены обновлять — вдруг изменились)
Один маленький замечаний по коду
выкладывать идентификатор сессии в публичный доступ из вэри бэд. Это слив куки.$id = session_id();
Да, конечно. Лучше использовать
uniqid()
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.