Задача: заполнить корзину пользователя теми же товарами и количествами которые были в ранее созданном заказе. При этом нужно очистить корзину от товаров которые в ней уже имеются
Решение задачи заключается в следующем:
- Получить текущую корзину пользователя и очистить ее
- Получить товары из ранее созданного заказа и заполнить ими корзину
Получение корзины пользователя и ее очистка
Мы используем метод Sale\Basket::loadItemsForFUser для получения корзины пользователя и цикл для обхода всех ее элементов с последующим удалением.
use Bitrix\Main\Loader;
use Bitrix\Sale;
global $USER;
if ($USER->IsAuthorized()) {
// Получаем корзину текущего пользователя
$basket = Sale\Basket::loadItemsForFUser(
Sale\Fuser::getId(),
Bitrix\Main\Context::getCurrent()->getSite()
);
foreach ($basket as $basketItem) {
// Отложенные не трогаем
if ($basketItem->getField('DELAY') === 'N') {
// Удаляем запись
$basket->getItemById($basketItem->getId())->delete();
// Сохраняем корзину
$basket->save();
}
}
}
- В начале скрипта мы подключаем необходимые классы и модули, такие как Sale\Basket и Bitrix\Main\Loader, чтобы иметь доступ к функционалу работы с корзиной и другими элементами сайта.
- Проверяем, авторизован ли текущий пользователь на сайте. Это важно, потому что мы будем работать с корзиной пользователя, и нам нужно убедиться, что это сделает только авторизованный пользователь.
- Получение корзины текущего пользователя: используем метод Sale\Basket::loadItemsForFUser для загрузки корзины текущего пользователя. Этот метод принимает идентификатор пользователя (Sale\Fuser::getId()) и сайт, на котором выполняется операция.
- Обход элементов корзины: используем цикл
foreach
для обхода всех элементов корзины пользователя. - Внутри цикла мы проверяем каждый элемент корзины на предмет отложенности. Если товар не отложен ('DELAY' === 'N'), удаляем элемент из корзины с помощью метода delete().
- После удаления товаров мы вызываем метод save() для сохранения изменений в корзине.
Копирование корзины заказа, добавление товара в корзину через API
Теперь нужно получить состав копируемого заказа. Точнее нам нужно получить корзину связанную с заказом и наполнить корзину пользователя ими:
$orderID = 4; // ID заказа
// Загружаем заказ
$order = Sale\Order::load($orderID);
if ($order) {
// Получаем корзину заказа
$orderBasket = $order->getBasket();
foreach ($orderBasket as $orderItem) {
$productID = $orderItem->getProductId();
$quantity = $orderItem->getQuantity();
// Добавляем товар в корзину
$basketItem = $basket->createItem(
'catalog',
$productID
);
// Дозаполняем
$basketItem->setFields(array(
'QUANTITY' => $quantity,
'CURRENCY' => $order->getCurrency(),
'LID' => $order->getSiteId(),
'PRODUCT_PROVIDER_CLASS' => '\CCatalogProductProvider',
));
}
$basket->save();
}
- Загружаем заказ с помощью метода Sale\Order::load, передавая идентификатор заказа.
- Проверяем, успешно ли загрузился заказ (if ($order)), чтобы убедиться, что заказ существует и был загружен.
- Получаем корзину заказа с помощью метода $order->getBasket(), который возвращает объект корзины, содержащий все товары заказа.
- Затем мы проходимся циклом foreach по товарам корзины заказа.
- Для каждого товара мы получаем его идентификатор ($productID) и количество ($quantity).
- Добавляем товар в текущую корзину ($basket) с помощью метода createItem.
- После создания элемента корзины мы устанавливаем его поля, такие как количество ('QUANTITY'), валюта ('CURRENCY'), сайт ('LID') и класс поставщика продукта ('PRODUCT_PROVIDER_CLASS'). Эти поля берутся из соответствующих полей заказа.
- Наконец, мы вызываем метод save() для сохранения изменений в корзине, тем самым добавляя все товары заказа в текущую корзину.
Код целиком, скрипт для повтора заказа по запросу
Например, в каком-то разделе вы выводите заказы и нужно дать пользователю повторить любой из них. Добавляем форму, которая отправит пользователя на файл с обработчиком, передав в POST ID заказа, и в конце скрипт перенаправит пользователя на офорление заказа:
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');
use Bitrix\Main\Loader;
use Bitrix\Sale;
global $USER;
if (!empty($_REQUEST['ORDER_ID_FOR_REPEAT'])) {
if ($USER->IsAuthorized()) {
$orderID = $_REQUEST['ORDER_ID_FOR_REPEAT'];
// Очищаем корзину пользователя
$basket = Sale\Basket::loadItemsForFUser(
Sale\Fuser::getId(),
Bitrix\Main\Context::getCurrent()->getSite()
);
foreach ($basket as $basketItem) {
// Отложенные не трогаем
if ($basketItem->getField('DELAY') === 'N') {
// Удаляем запись
$basket->getItemById($basketItem->getId())->delete();
// Сохраняем корзину
$basket->save();
}
}
// Загружаем заказ
$order = Sale\Order::load($orderID);
if ($order) {
// Получаем корзину заказа
$orderBasket = $order->getBasket();
foreach ($orderBasket as $orderItem) {
$productID = $orderItem->getProductId();
$quantity = $orderItem->getQuantity();
// Добавляем товар в корзину
$basketItem = $basket->createItem(
'catalog',
$productID
);
// Дозаполняем
$basketItem->setFields(array(
'QUANTITY' => $quantity,
'CURRENCY' => $order->getCurrency(),
'LID' => $order->getSiteId(),
'PRODUCT_PROVIDER_CLASS'=>'\CCatalogProductProvider',
));
}
$basket->save();
}
// Отправляем на офорление уже с новой корзиной
LocalRedirect('/personal/order/make/');
}
} else {
LocalRedirect('/');
}
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_after.php');
Скрипт-обработчик лучше всего завернуть в компонент с настройками и дополнительными проверками. Привел как есть, что бы не усложнять.