Как работать с корзиной в D7 Битрикс

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

Простые классы

Для добавления товара в корзину в D7 существует класс Bitrix\Catalog\Product\Basket c аналогом метода Add2BasketByProductID

<?
\Bitrix\Main\Loader::includeModule('catalog');
$result = Bitrix\Catalog\Product\Basket::addProduct(
[
'PRODUCT_ID' => $id, // id товара или предложения
],
[
'QUANTITY' => $quantity, // количество
'PROPS' => [
[
'NAME' => 'Размер',
'CODE' => 'SIZE',
'VALUE' => '180',
'SORT' => '100',
],
],
]
);
if (!$result->isSuccess())
{
\Bitrix\Main\Diag\Debug::dump($result->getErrorMessages());
}

ORM-классы

Обновить товар в корзине с помощью того же класса не получится, но можно сделать с помощью ORM-класса Bitrix\Sale\Internals\BasketTable

Но для того, чтобы обновить товар в корзине, нужно знать ID корзины. Получить его можно с помощью метода GetList:

<?
\Bitrix\Main\Loader::includeModule('sale');
$arBasketItem = Bitrix\Sale\Internals\BasketTable::getList([
'filter' => [
'FUSER_ID' => Bitrix\Sale\Fuser::getId(), // ID покупателя, это может быть неавторизованный пользователь
'ORDER_ID' => null, // если заказ создан, передаем id заказа
'PRODUCT_ID' => $id, // id товара или предложения
'LID' => Bitrix\Main\Context::getCurrent()->getSite(), // работает только из публички, в другом случае можно указать жестко "s1"
'CAN_BUY' => 'Y',
],
'select' => [
'ID',
'PRODUCT_ID',
'QUANTITY',
],
])->fetch();

Теперь, зная идентификатор, можно обновить корзину:

<?
$result = Bitrix\Sale\Internals\BasketTable::update($basketId, [
'QUANTITY' => $quantity,
]);
if (!$result->isSuccess())
{
\Bitrix\Main\Diag\Debug::dump($result->getErrorMessages());
}

С помощью этого ORM-класса также можно и добавлять товары в корзину с помощью метода add, но я не рекомендую этого делать из-за низкоуровневости его работы – могут некоторые поля потеряться.

Свойства

Обновить свойства корзины с помощью класс BasketTable у вас не получится, так как Корзина и Свойства корзины – это разные таблицы. Поэтому для свойств корзины есть свой ORM-класс Bitrix\Sale\Internals\BasketPropertyTable

Чтобы добавить новое свойство корзины, нужно знать ее идентификатор:

<?
Bitrix\Sale\Internals\BasketPropertyTable::add([
'BASKET_ID' => $basketId, // id позиции корзины
'NAME' => 'Вес',
'CODE' => 'WEIGHT',
'VALUE' => '2 кг',
]);

А вот, чтобы обновить свойство нужно знать его идентификатор. Его можно получить с помощью getList и затем обновить значение свойства:

<?
// получаем id свойства
$propSize = Bitrix\Sale\Internals\BasketPropertyTable::getList([
'filter' => [
'=BASKET_ID' => $basketId, // id позиции корзины
'=CODE' => 'SIZE',
],
'select' => [
'ID',
],
])->fetch();
if ($propSize)
{
// обновляем значение свойства
$result = Bitrix\Sale\Internals\BasketPropertyTable::update($propSize['ID'], [
'VALUE' => '100',
]);
if (!$result->isSuccess())
{
\Bitrix\Main\Diag\Debug::dump($result->getErrorMessages());
}
}

Универсальные классы

Более крутой способ работы с корзиной – использование класса Bitrix\Sale\Basket.

Если вы работаете в phpStorm не забудьте подключать автоподсветку для классов в блоке с комментариями. Они очень помогут разобраться.

Способы получения объекта корзины:

<?
\Bitrix\Main\Loader::includeModule('sale');
$fuser = \Bitrix\Sale\Fuser::getId();
/**
* @var \Bitrix\Sale\Basket $basket
*/
$basket = Bitrix\Sale\Basket::loadItemsForFUser($fuser, SITE_ID);
// если корзина привязана заказа, можно получить так:
// по объекту заказа (Bitrix\Sale\Order)
$basket = Bitrix\Sale\Basket::loadItemsForOrder($order);
// по id заказа
$basket = Bitrix\Sale\Order::load($orderId)->getBasket();
// по номеру заказа
$basket = Bitrix\Sale\Order::loadByAccountNumber($orderNum)->getBasket();

Способы добавления товаров в корзину:

<?
/**
* @var \Bitrix\Sale\BasketItem $basketItem
*/
// первый вариант
$basketItem = $basket->createItem('catalog', $productId); // id товара или предложения
$basketItem->setField('QUANTITY', 1);
// второй вариант
$basketItem = \Bitrix\Sale\BasketItem::create($basket, 'catalog', $productId);
$basketItem->setField('QUANTITY', 1);
$basket->addItem($basketItem);
// не забываем сохранить
$basket->save();

Из корзины можно получить объект интересующей нас позицию, зная ID:

<?
/**
* @var \Bitrix\Sale\BasketItem $basketItem
*/
$basketItem = $basket->getItemById($basketId); // id позиции корзины
// какие-нибудь действия
$basketItem->setField('QUANTITY', 3);
\Bitrix\Main\Diag\Debug::dump($basketItem->getFieldValues());
$basket->save();

Пример для демонстрации возможности работы с корзиной

<?
\Bitrix\Main\Loader::includeModule('sale');
$fuser = \Bitrix\Sale\Fuser::getId();
/**
* @var \Bitrix\Sale\Basket $basket
* @var \Bitrix\Sale\BasketItem $basketItem
*/
$basket = Bitrix\Sale\Basket::loadItemsForFUser($fuser, SITE_ID);
foreach ($basket->getBasketItems() as $basketItem)
{
// получение количества
$quantity = $basketItem->getField('QUANTITY'); // или getQuantity()
// запись количества
$basketItem->setField('QUANTITY', $quantity++);
\Bitrix\Main\Diag\Debug::dump($basketItem->getFieldValues()); // получить все поля позиции в корзине
// добавление или обновление свойства
$propCollection = $basketItem->getPropertyCollection();
$props = $propCollection->getPropertyValues();
$props['DESC'] = [
'NAME' => 'Описание',
'CODE' => 'DESC',
'VALUE' => 'test',
];
$propCollection->redefine($props); // или использовать старый setProperty
}
// не забываем сохранить
$basket->save();

Запомните, что для работы с полями используются getField и setField, для свойств – как на примере выше получаем коллекцию.

Часто используемые функции:

  • Получить количество товара в корзине $basketItem->getQuantity()
  • Получить идентификатор корзины $basketItem->getProductId()
  • Получить идентификатор товара $basketItem->getId()
  • Получить цену товара $basketItem->getPrice()
  • Записать количество $basketItem->setField(‘QUANTITY’, 2)
  • Получить название $basketItem->getField(‘NAME’)
  • Удалить корзину $basketItem->delete()
  • Возвратить объект заказа, к которому привязана корзина $basket->getOrder()
  • Записать сразу несколько полей $basketItem->setFields([])

Вы можете получить все поля с помощью $basketItem->getFieldValues() и подглядеть коды полей, чтобы затем управлять с помощью методов getField и setField.

Пример создания новой корзины и привязки к заказу

<?
/**
* @var Bitrix\Sale\Order $order
* @var \Bitrix\Sale\Basket $basket
* @var \Bitrix\Sale\BasketItem $basketItem
*/
\Bitrix\Main\Loader::includeModule('sale');
\Bitrix\Main\Loader::includeModule('currency');
$currencyCode = Bitrix\Currency\CurrencyManager::getBaseCurrency();
$newBasket = Bitrix\Sale\Basket::create($siteId);
// добавляем id предложений из массива в корзину
foreach ($offerIds as $offerId)
{
$basketItem = $newBasket->createItem('catalog', $offerId);
$basketItem->setFields([
'QUANTITY' => 1,
'CURRENCY' => $currencyCode,
'LID' => Bitrix\Main\Context::getCurrent()->getSite(),
'PRODUCT_PROVIDER_CLASS' => '\Bitrix\Catalog\Product\CatalogProvider',
]);
$properties = [];
foreach ($props as $property)
{
$properties[] = [
'NAME' => $property['NAME'],
'CODE' => $property['CODE'],
'VALUE' => $property['VALUE'],
];
}
$basketPropertyCollection = $basketItem->getPropertyCollection();
$basketPropertyCollection->redefine($properties);
$newBasket->save();
}
// привязываем корзину к заказу
$order = Bitrix\Sale\Order::load($orderId);
$order->setBasket($basket);
$order->save();

Заключение

На этом все. В документации Битрикса вы также можете найти подсказки и ответы на свои вопросы. Все моменты, конечно сложно рассмотреть в одной статье, поэтому если у вас есть вопросы, замечания или что добавить – пишите комментарии.