Работа с корзиной в Битрикс D7, bitrix.basket.basket
Rus
Eng
Работа с корзиной в Битрикс D7

Навигация по разделам:

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

Начиная с 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), обновление записи и проверка наличия:

//количество
$quantity = 1;

//ID товара (торговый каталог)
$productId = 233;

// Получение корзины для текущего пользователя
$basket = \Bitrix\Sale\Basket::loadItemsForFUser(
   \Bitrix\Sale\Fuser::getId(), 
   \Bitrix\Main\Context::getCurrent()->getSite()
);

if ($item = $basket->getExistsItem('catalog', $productId)){

   //Обновление товара в корзине
   $item->setField('QUANTITY', $item->getQuantity() + $quantity);
}else{

   //Добавление товара
   $item = $basket->createItem('catalog', $productId);
   $item->setFields([
      'QUANTITY' => $quantity,
      'CURRENCY' => \Bitrix\Currency\CurrencyManager::getBaseCurrency(),
      'LID' => \Bitrix\Main\Context::getCurrent()->getSite(),
      'PRODUCT_PROVIDER_CLASS' => \Bitrix\Catalog\Product\Basket::getDefaultProviderName() ,
   ]);
}

//Сохранение изменений
$basket->save();
    /* 
    Если вы хотите добавить товар с произвольной ценой, нужно сделать так:
    $item->setFields(array(
        'QUANTITY' => $quantity,
        'CURRENCY' => Bitrix\Currency\CurrencyManager::getBaseCurrency(),
        'LID' => Bitrix\Main\Context::getCurrent()->getSite(),
        'PRICE' => $customPrice,
        'CUSTOM_PRICE' => 'Y',
   ));
   */

В одной из новых версий модуля catalog был добавлен функционал добавления в корзину:

require_once($_SERVER['DOCUMENT_ROOT'].'/bitrix/modules/main/include/prolog_before.php');

use Bitrix\Main\Application;

Bitrix\Main\Loader::includeModule("catalog");

$request = Application::getInstance()->getContext()->getRequest();

$fields = [
    'PRODUCT_ID' => intval($request->getPost("id")), // ID товара, обязательно
    'QUANTITY' => intval($request->getPost("quantity")), // количество, обязательно
    'PROPS' => [
        ['NAME' => 'basket_detail', 'CODE' => 'basket_detail', 'VALUE' => $request->getPost("basket_detail")],
    ],

];

$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() . '
';
}

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

$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();

Обновление свойств товара при его добавлении в корзину

Допустим нам нужно обновить или добавить некоторые свойства товара в корзине до его добавления туда в зависимости от параметров.

В моем случае мне надо было вывести checkbox в корзине. И в зависимости от комбинаций условий POST запроса и свойств товара выставлять его значение checked как true или false

Добавляем в init.php

use Bitrix\Main\EventManager;

$eventManager = EventManager::getInstance();

$eventManager->addEventHandler('sale','OnSaleBasketBeforeSaved', ["AvtoHandlers", "OnSaleBasketBeforeSaved"]);

class AvtoHandlers
{
    function OnSaleBasketBeforeSaved(Main\Event $event)
    {
        \CModule::IncludeModule('iblock');

        $request = Application::getInstance()->getContext()->getRequest();

        /** @var Basket $basket */
        $basket = $event->getParameter("ENTITY");
        $basketItems = $basket->getBasketItems();
        foreach ($basketItems as $basketItem) {
            if ($basketItem->getProductId() != $request->get('id')) {
                continue;
            }

            $rs = CIBlockElement::GetList(
                Array(),
                Array("ID" => $basketItem->getProductId()),
                false,
                false,
                array('ID', 'IBLOCK_ID', 'PROPERTY_STOIMOST_DONORSKOY_ZAPCHASTI')
            )->fetch();
            if (!$rs || empty($rs['PROPERTY_STOIMOST_DONORSKOY_ZAPCHASTI_VALUE'])) {
                continue;
            }

            $isCustomPrice = $basketItem->getField('CUSTOM_PRICE') ? $basketItem->getField('CUSTOM_PRICE') : 'N';

            // свойство POST и товара не совпадают
            if ($request->get('basket_detail') == 'N' && $isCustomPrice == 'N') {
                $basketItem->setFields(array(
                    'PRICE' => $basketItem->getPrice() + $rs['PROPERTY_STOIMOST_DONORSKOY_ZAPCHASTI_VALUE'],
                    'CUSTOM_PRICE' => 'Y',
                ));
            }

            // свойство POST и товара совпадают
            if ($request->get('basket_detail') == 'Y' && $isCustomPrice == 'Y') {
                $basketItem->setFields(array(
                    'PRICE' => $basketItem->getPrice() - $rs['PROPERTY_STOIMOST_DONORSKOY_ZAPCHASTI_VALUE'],
                    'CUSTOM_PRICE' => 'N',
                ));
            }
        }

        return new Main\EventResult(Main\EventResult::SUCCESS);

    }
}

В самой корзине идем в файл /local/templates/Ваш_шаблон_сайта/components/bitrix/sale.basket.basket/Ваш_шаблон_корзины/mutator.php и добавляем в цикле foreach ($this->basketItems as $row) {

//Дополнительный параметр
if (!empty($row['PROPERTY_STOIMOST_DONORSKOY_ZAPCHASTI_VALUE'])) {
	$rowData['DONOR_PRICE'] = $row['PROPERTY_STOIMOST_DONORSKOY_ZAPCHASTI_VALUE'];
	if ($row['CUSTOM_PRICE'] == 'N') {
		$rowData['DONOR_GIVE'] = true;
	}
}

А в файле local/templates/Ваш_шаблон_сайта/components/bitrix/sale.basket.basket/Ваш_шаблон_корзины/js-templates/basket-item.php в нужном месте вставляем

{{#DONOR_PRICE}}
<input data-donor-checker="Y" data-basket-item-id="{{ID}}" data-product-id="{{PRODUCT_ID}}"
	   data-quantity="{{QUANTITY}}" id="basket_detail_{{ID}}" name="basket_detail_{{ID}}"
	   class="js--basket_detail" value="Y" type="checkbox" {{#DONOR_GIVE}}checked="checked"{{/DONOR_GIVE}} />
<label for="basket_detail_{{ID}}">Текст вашего checkbox</label>
{{/DONOR_PRICE}}

Решение применялось на редакции Малый бизнес v18.1.8

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

Обновление компонента sale.basket.basket после ajax запроса

BX.Sale.BasketComponent.sendRequest('refreshAjax', {fullRecalculation: 'Y'});

BX.Sale.BasketComponent.fillTotalBlocks();
for(itemId in BX.Sale.BasketComponent.items){
	if(BX.Sale.BasketComponent.items.hasOwnProperty(itemId)){
		BX.Sale.BasketComponent.redrawBasketItemNode(itemId);
	}
}

Обновление компонента sale.basket.line после ajax запроса

Определение события в шаблоне template.php

BX.addCustomEvent(window, 'OnBasketChange', sbbl.refreshCart);

Вызов события в скрипте

BX.onCustomEvent('OnBasketChange');

Анимация добавления товара в корзину

Допустим, что у нас есть кнопка в корзину с классом js-basket-simple

И нам нужно, чтобы при клике на нее, произошла анимация добавления товара в корзину. Мы пойдем наиболее простым путем - добавим на место кнопки элементы и анимируем путь от него до нашей корзины. Весь код будет выглядеть так:

function sSend(e) {
	//Получаем координаты элемента, где должен быть отображен дополнительный летающий слой
    var x = e.pageX,
        y = e.pageY;

	//Вставляем новый див с svg изображением корзины, который будет лететь к корзине и уменьшаться
    $('body').append('<div class="toCart" style="position:absolute;fill:#FF0000;width:25px;height:25px;border-radius:100px;z-index:9999999999;left:'+x+'px;top:'+y+'px;"><svg width="25" height="25" style="max-width: 100%" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">\n' +
        '\t\t\t\t\t\t\t\t\t<path d="M30.5255 31.203L28.1345 8.92653C28.0947 8.56787 27.7758 8.28892 27.4172 8.28892H22.9938V6.934C22.9938 3.10834 19.8854 0 16.0598 0C12.2341 0 9.12579 3.10834 9.12579 6.934V8.28892H4.58282C4.22417 8.28892 3.90536 8.56787 3.86551 8.92653L1.47448 31.203C1.43463 31.4022 1.51433 31.6015 1.63388 31.7609C1.75343 31.9203 1.95268 32 2.15194 32H29.8481C30.0473 32 30.2466 31.9203 30.3661 31.7609C30.4857 31.6015 30.5654 31.4022 30.5255 31.203ZM22.2765 12.3138C22.6351 12.3138 22.9141 12.5928 22.9141 12.9514C22.9141 13.3101 22.6351 13.589 22.2765 13.589C21.9178 13.589 21.6389 13.3101 21.6389 12.9514C21.6389 12.5928 21.9178 12.3138 22.2765 12.3138ZM10.5604 6.934C10.5604 3.90535 13.0311 1.43462 16.0598 1.43462C19.0884 1.43462 21.5592 3.90535 21.5592 6.934V8.28892H10.5604V6.934ZM9.8431 12.3138C10.2018 12.3138 10.4807 12.5928 10.4807 12.9514C10.4807 13.3101 10.2018 13.589 9.8431 13.589C9.48444 13.589 9.20549 13.3101 9.20549 12.9514C9.20549 12.5928 9.48444 12.3138 9.8431 12.3138ZM2.9888 30.5255L5.22043 9.68369H9.12579V10.9988C8.32877 11.2777 7.77087 12.0349 7.77087 12.9116C7.77087 14.0274 8.68743 14.944 9.80325 14.944C10.9191 14.944 11.8356 14.0274 11.8356 12.9116C11.8356 12.0349 11.2777 11.2777 10.4807 10.9988V9.68369H21.4795V10.9988C20.6824 11.2777 20.1245 12.0349 20.1245 12.9116C20.1245 14.0274 21.0411 14.944 22.1569 14.944C23.2727 14.944 24.1893 14.0274 24.1893 12.9116C24.1893 12.0349 23.6314 11.2777 22.8344 10.9988V9.68369H26.8991L29.1308 30.5255H2.9888Z" fill="#EB5255"></path>\n' +
        '\t\t\t\t\t\t\t\t</svg></div>');
	
	//Класс нашей корзины, сюда будет лететь элемент
    var cart = $('.header-cart').offset();

    $('.toCart').animate({ top: cart.top + 'px', left: cart.left + 'px', width: 0, height: 0 }, 1300, function(){
        $(this).remove();
    });

}

(function ($) {
    $(document).on('click','.js-basket-simple',function(e){
        sSend(e);
    });
})(jQuery);

Использована информация с сайта mrcappuccino

Комментарии

Комментариев еще нет, Вы можете стать первым кто его оставит

Оставьте комментарий

На сайте используется система премодерирования комментариев, поэтому ваше сообщение будет опубликовано лишь после одобрения модератором

Вы отвечаете на комментарий пользователя

Отправить

ОБРАТНАЯ СВЯЗЬ

Напишите мне

Вы разрабатываете новый сервис, вносите доработки в существующий и хотите лучше чем у конкурентов? Вы обратились по адресу. Предлагаю вам комплексную разработку сайтов студийного уровня. У меня вы можете заказать дизайн, верстку, програмированние, разработку нетрадиционного функционала, реализацию связи между CMS, CRM и Data Analitics, а так же все остальное касаемое сайтов, кроме продвижения.

Обращайтесь, я всегда проконсультирую по всем вопросам и помогу подобрать наиболее эффективное решение для Вашего бизнеса. Я занимаюсь созданием сайтов в Новосибирске и в других регионах России, также работаю со странами СНГ. Вы останетесь довольны нашим сотрудничеством

Во время отправки произошла ошибка, пожалуйста попробуйте еще раз через некоторое время
Сообщение отправлено успешно

Телефоны

+7(993) 007-18-96

Email

info@tichiy.ru

Адрес

Россия, г. Москва

Отправляя форму Вы автоматически подтверждаете, что ознакомились и принимаете Политику конфиденциальности сайта

Написать мне
Отправить
Отправляя форму Вы автоматически подтверждаете, что ознакомились и принимаете Политику конфиденциальности сайта
Отправка успешна!
Thank you for your feedback. I will answer you within the next working hours
Отправка не удалась
Во время отправки запроса произошла ошибка. Пожалуйста, подождите и попробуйте снова через некоторое время или свяжитесь со мной