Все классы для работы с магазином собраны в модуле sale. Поэтому для работы с корзиной битрикс необходимо подключить пространство имен модуля интернет-магазина:
use Bitrix\Sale;Корзина
Корзина в Bitrix представляет собой экземпляр класса Bitrix\Sale\Basket. Для текущего пользователя получить корзину можно следующим образом:
$basket = Sale\Basket::loadItemsForFUser(Sale\Fuser::getId(), Bitrix\Main\Context::getCurrent()->getSite());Метод getSite не работает в админке. Работает только в публичной части.
Можно получить корзину заказа:
/** int $orderId номер заказа */
$basket = Sale\Order::load($orderId)->getBasket();
// или:
/** Sale\Basket $order объект заказа */
$basket = Sale\Basket::loadItemsForOrder($order);Получить информацию о корзине:
$price = $basket->getPrice(); // Цена с учетом скидок
$fullPrice = $basket->getBasePrice(); // Цена без учета скидок
$weight = $basket->getWeight(); // Общий вес корзиныДобавление товара в корзину (аналог CSaleBasket::Add), обновление записи и проверка наличия:
/** int $productId ID товара */
/** int $quantity количество */
if ($item = $basket->getExistsItem('catalog', $productId)) {
$item->setField('QUANTITY', $item->getQuantity() + $quantity);
}
else {
$item = $basket->createItem('catalog', $productId);
$item->setFields(array(
'QUANTITY' => $quantity,
'CURRENCY' => Bitrix\Currency\CurrencyManager::getBaseCurrency(),
'LID' => Bitrix\Main\Context::getCurrent()->getSite(),
'PRODUCT_PROVIDER_CLASS' => 'CCatalogProductProvider',
));
/*
Если вы хотите добавить товар с произвольной ценой, нужно сделать так:
$item->setFields(array(
'QUANTITY' => $quantity,
'CURRENCY' => Bitrix\Currency\CurrencyManager::getBaseCurrency(),
'LID' => Bitrix\Main\Context::getCurrent()->getSite(),
'PRICE' => $customPrice,
'CUSTOM_PRICE' => 'Y',
));
*/
}
$basket->save();В одной из новых версий модуля catalog был добавлен функционал добавления в корзину:
Bitrix\Main\Loader::includeModule("catalog");
$fields = [
'PRODUCT_ID' => 98, // ID товара, обязательно
'QUANTITY' => 2, // количество, обязательно
'PROPS' => [
['NAME' => 'Test prop', 'CODE' => 'TEST_PROP', 'VALUE' => 'test value'],
],
];
$r = Bitrix\Catalog\Product\Basket::addProduct($fields);
if (!$r->isSuccess()) {
var_dump($r->getErrorMessages());
}Данный метод проверяет доступность товара к покупке (при отсутствии будет возвращен результат с ошибкой «Товар отсутствует»), сам проверяет наличие товара в корзине и при наличии увеличивает количество товара в корзине. Также к товару добавляются свойства корзины, необходимые для обмена с 1С: PRODUCT.XML_ID и CATALOG.XML_ID. Но при этом нет возможности передать в корзину кастомную цену.
Получение записи по ID и удаление записи из корзины (аналог CSaleBasket::Delete):
/** int $id ID записи */
$basket->getItemById($id)->delete();
$basket->save();Получение товаров в корзине, доступных для покупки (CAN_BUY=Y):
$orderBasket = $basket->getOrderableItems();Также есть пара методов для получения корзины в виде, пригодной для использования в письме или для вывода количества товаров:
var_dump($basket->getListOfFormatText()); // возвращает корзину в читаемом виде:
// array(2) { [11]=> string(101) "Тарелка [Цвет: Кофе с молоком] - 2 : 2 199 руб." [12]=> string(65) "Кружка - 1 : 1 899 руб." }
var_dump($basket->getQuantityList()); // возвращает массив "количеств" товаров в корзине:
// array(3) { [11]=> float(2) [12]=> float(1) }
var_dump(array_sum($basket->getQuantityList())); // float(3) - количество товаров в корзине
var_dump(count($basket->getQuantityList())); // int(2) - количество позиций в корзинеТовар в корзине (Sale\BasketItem)
Товары в корзине представлены в виде коллекции объектов класса Bitrix\Sale\BasketItem:
$basketItems = $basket->getBasketItems(); // массив объектов Sale\BasketItemSale\Basket реализует интерфейсы \ArrayAccess, \Countable и \IteratorAggregate, поэтому с объектом корзины можно обращаться как с массивом, получая товары в корзине по индексу или перебирая записи с помощью foreach:
foreach ($basket as $basketItem) {
echo $basketItem->getField('NAME') . ' - ' . $basketItem->getQuantity() . '<br />';
}Информация о товарах в корзине:
$basketItem = $basketItems[0];
$basketItem->getId(); // ID записи в корзине
$basketItem->getProductId(); // ID товара
$basketItem->getPrice(); // Цена за единицу
$basketItem->getQuantity(); // Количество
$basketItem->getFinalPrice(); // Сумма
$basketItem->getWeight(); // Вес
$basketItem->getField('NAME');// Любое поле товара в корзине
$basketItem->canBuy(); // true, если доступно для покупки
$basketItem->isDelay(); // true, если отложеноТакже из записи можно получить другие сущности:
$basketItem->getPropertyCollection(); // Свойства товара в корзине, коллекция объектов Sale\BasketPropertyItem, см. ниже
$basketItem->getCollection(); // Корзина, в которой лежит товар Действия над записями:
$basketItem->setField('QUANTITY', $quantity); // Изменение поля
$basketItem->setFields(array(
'QUANTITY' => $quantity,
'PRICE' => $customPrice, // Вводим кастомную цену
'CUSTOM_PRICE' => 'Y', // Разрешаем изменение цены на кастомную
)); // Изменение полей
$basketItem->delete(); // Удаление
$basketItem->save(); // Сохранение изменения, можно использовать и $basket->save();Свойства товаров в корзине (Sale\BasketPropertiesCollection)
У товара в корзине можно получить коллекцию свойств — объект Bitrix\Sale\BasketPropertiesCollection:
/** Sale\BasketItem $item объект товара в корзине */
$basketPropertyCollection = $basketItem->getPropertyCollection();
$basketPropertyCollection->getPropertyValues();Метод getPropertyValues возвращает массив свойств.
Добавить новое свойство или изменить существующие можно следующим образом:
$basketPropertyCollection->setProperty(array(
array(
'NAME' => 'Цвет',
'CODE' => 'COLOR',
'VALUE' => 'Кофе с молоком',
'SORT' => 100,
),
));
$basketPropertyCollection->save();Не забывайте, что метод setProperty() Перезатрет существующие свойства в корзине. Чтобы такого не было, нужно получить все свойства, и через setProperty записать все свойства вместе
$properties = $basketItem->getPropertyCollection();
// Сначала получаем существующие свойства
$existingProperties = [];
foreach ($properties as $property) {
if ($property->getField('CODE') !== 'PRICE_FOR_CUR_USER') {
$existingProperties[] = array(
'NAME' => $property->getField('NAME'),
'CODE' => $property->getField('CODE'),
'VALUE' => $property->getField('VALUE'),
'SORT' => $property->getField('SORT'),
);
}
}
Пример удаления свойства:
foreach ($basketPropertyCollection as $propertyItem) {
if ($propertyItem->getField('CODE') == 'COLOR') {
$propertyItem->delete();
break;
}
}
$basketPropertyCollection->save();ORM-классы
Обращаться напрямую к таблице корзины, без использования объектов можно с использованием ORM-класса Bitrix\Sale\Internals\BasketTable. Например, перебрать товары в корзине текущего пользователя:
$basketRes = Sale\Internals\BasketTable::getList(array(
'filter' => array(
'FUSER_ID' => Sale\Fuser::getId(),
'ORDER_ID' => null,
'LID' => SITE_ID,
'CAN_BUY' => 'Y',
)
));
while ($item = $basketRes->fetch()) {
var_dump($item);
}А так можем получить количество и сумму товаров в корзине текущего юзера:
$result = Sale\Internals\BasketTable::getList(array(
'filter' => array(
'FUSER_ID' => Sale\Fuser::getId(),
'ORDER_ID' => null,
'LID' => SITE_ID,
'CAN_BUY' => 'Y',
),
'select' => array('BASKET_COUNT', 'BASKET_SUM'),
'runtime' => array(
new \Bitrix\Main\Entity\ExpressionField('BASKET_COUNT', 'COUNT(*)'),
new \Bitrix\Main\Entity\ExpressionField('BASKET_SUM', 'SUM(PRICE*QUANTITY)'),
)
))->fetch();Получить свойства товаров в корзине поможет класс Bitrix\Sale\Internals\BasketPropertyTable:
$basketPropRes = Sale\Internals\BasketPropertyTable::getList(array(
'filter' => array(
"BASKET_ID" => $basketItemId,
),
));
while ($property = $basketPropRes->fetch()) {
var_dump($property);
}Полезные функции
Функция удаляет брошенные корзины пользователей. Намомню, корзины находятся по адресу https://site_address/bitrix/admin/sale_basket.php. Работает просто — получаем все корзины всех пользователей и очищаем их.
function deleteBasket()
{
$obBasket = \Bitrix\Sale\Basket::getList(
array(
'select' => array(
'FUSER_ID'
),
'filter' => array(
'ORDER_ID' => 'NULL',
),
)
);
while($bItem = $obBasket->Fetch()){
CSaleBasket::DeleteAll(
$bItem['FUSER_ID'],
False
);
}
}
Об авторе
Сергей Житников - Веб-разработчик
Занимаюсь веб-разработкой более 5 лет. Специализируюсь на создании адаптивных сайтов и веб-приложений на HTML5, CSS3 и JavaScript. Работаю с популярными CMS и фреймворками, а также уделяю большое внимание оптимизации производительности и чистоте кода.
Есть проект или идея? Буду рад помочь!
Связаться со мной