Начиная с 16 версии используется новая версия ядра магазина Битрикс, являющаяся частью ядра Битрикс D7. Но некоторые классы и методы доступны и в 15 версии магазина (sale, не main). Все классы для работы с магазином собраны в модуле sale, поэтому для работы с примерами в статье используем use для пространства имён модуля интернет-магазина.

use Bitrix\Sale;

Корзина (Sale\Basket)

Корзина представляет собой экземпляр класса 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\BasketItem

Sale\Basket реализует интерфейсы \ArrayAccess, \Countable и \IteratorAggregate, поэтому с объектом корзины можно обращаться как с массивом, получая товары в корзине по индексу или перебирая записи с помощью foreach:

foreach ($basket as $basketItem) {
    echo $basketItem->getField('NAME') . ' - ' . $basketItem->getQuantity() . '<br />';
}

Информация о товарах в корзине:

$item = $basketItems[0];
$item->getId();         // ID записи в корзине
$item->getProductId();  // ID товара
$item->getPrice();      // Цена за единицу
$item->getQuantity();   // Количество
$item->getFinalPrice(); // Сумма
$item->getWeight();     // Вес
$item->getField('NAME');// Любое поле товара в корзине
$item->canBuy();        // true, если доступно для покупки
$item->isDelay();       // true, если отложено

Также из записи можно получить другие сущности:

$item->getPropertyCollection(); // Свойства товара в корзине, коллекция объектов Sale\BasketPropertyItem, см. ниже
$item->getCollection();         // Корзина, в которой лежит товар 

Действия над записями:

$item->setField('QUANTITY', $quantity); // Изменение поля
$item->setFields(array(
    'QUANTITY' => $quantity,
    'CUSTOM_PRICE' => $customPrice,
)); // Изменение полей

$item->delete(); // Удаление
$item->save();   // Сохранение изменения, можно использовать и $basket->save();

Свойства товаров в корзине (Sale\BasketPropertiesCollection)

У товара в корзине можно получить коллекцию свойств - объект Bitrix\Sale\BasketPropertiesCollection:

/** Sale\BasketItem $item объект товара в корзине */
$basketPropertyCollection = $item->getPropertyCollection(); 
$basketPropertyCollection->getPropertyValues();

Метод getPropertyValues возвращает массив свойств.

Добавить новое свойство или изменить существующие можно следующим образом:

$basketPropertyCollection->setProperty(array(
    array(
       'NAME' => 'Цвет',
       'CODE' => 'COLOR',
       'VALUE' => 'Кофе с молоком',
       'SORT' => 100,
    ),
));
$basketPropertyCollection->save();

Пример удаления свойства:

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);
}

Читайте также: