Заказы и корзины в современной редакции Битрикса. Конспект вебинара
Часть 1 / Часть 2 / Часть 3
Вебинар:
Трансформации начались с момента выпуска совершенно нового движка магазина. Чтобы обновиться, необходимо было провести конвертацию заказов.
Проблемы и запросы клиентов:
- «Длинные» заказы у крупного бизнеса == громоздкие запросы в большом количестве;
- Нужны частичные отгрузки, нужны частичные оплаты;
- Архив заказов;
- Перевод публичных и админских механизмов на одинаковый механизм и логику.
Одна из характеристик нового подхода: обрабатывать во время записи только те данные, которые реально обновились.
Два основных класса
\Bitrix\Sale\Order
и \Bitrix\Sale\Basket
Специфика: работать с объектом как с единым целым и сохранять данные только у головной сущности. Механика нового подхода сама решит, что внутри изменилось, что требует сохранения в базу данных и пересчёт.
¶Примеры кода и ошибок:
Исходная ситуация: получаем текущий заказ и добавляем товар
\Bitrix\Main\Loader::includeModule('sale');
$orderId = 752;
$order = \Bitrix\Sale\Order::load($orderId);
$productId = 412;
$basket = $order->getBasket();
$basketItem = $basket->createItem('catalog', $productId);
// Вариант 1:
// Устанавливаем количество товаров 5
$basketItem->setField('QUANTITY', 5);
// Ставим цену и маркируем её как кастомную
$basketItem->setPrice(175, true);
// Вариант 2:
$basketItem->setFields([
'QUANTITY' => 5,
'PRICE' => 175,
'CUSTOM_PRICE' => 'Y'
]);
// Сохраняем головную сущность
$order->save();
Ошибка:
// Головной объект (заказ)
// фактически не обновлён
// и значит не произведены
// необходимые пересчёты
$basket->save();
Излишне (двойное сохранение):
$basket->save();
$order->save();
Правильно:
$order->save();
¶Современный подход
После выпуска топ-редакции (1С-Битрикс24: Интернет-магазин+CRM), чтобы код работы с главными сущностями интернет-магазина был универсальным, следует работать с реестром классов:
use Bitrix\Sale\BasketBase;
use Bitrix\Sale\Fuser;
use Bitrix\Sale\OrderBase;
use Bitrix\Sale\Registry;
// Получаем объект, заведующий реестрами
$registry = Registry::getInstance(Registry::REGISTRY_TYPE_ORDER);
/**
* @var $orderClass OrderBase
* @var $basketClass BasketBase
*/
// Получаем класс работы с заказами
$orderClass = $registry->getOrderClassName();
// Получаем класс работы с корзинами
$basketClass = $registry->getBasketClassName();
// Читаем заказ
$order = $orderClass::load($orderId);
// Читаем корзину из объекта заказа
$basket = $order->getBasket();
// Читаем корзину через класс по объекту заказа
$basket = $basketClass::loadItemsForOrder($order);
// Читаем корзину для текущего покупателя
$currentFUser = Fuser::getId();
$basket = $basketClass::loadItemsForFUser($currentFUser, SITE_ID);
/**
* @var \Bitrix\Sale\BasketItem $bi
*/
// Добываем данные по полям товаров в корзине
foreach ($basket->getBasketItems() as $bi) {
$basketProductFields = $bi->getFieldValues();
}
Использование библиотеки регистров открывает возможности по кастомизации локальных движков методом регистрации своих классов-обработчиков
¶Список стандартных классов в реестре заказов:
Registry::ENTITY_ORDER =>
'\Bitrix\Sale\Order',
Registry::ENTITY_PAYMENT =>
'\Bitrix\Sale\Payment',
Registry::ENTITY_PAYMENT_COLLECTION =>
'\Bitrix\Sale\PaymentCollection',
Registry::ENTITY_SHIPMENT =>
'\Bitrix\Sale\Shipment',
Registry::ENTITY_SHIPMENT_COLLECTION =>
'\Bitrix\Sale\ShipmentCollection',
Registry::ENTITY_SHIPMENT_ITEM =>
'\Bitrix\Sale\ShipmentItem',
Registry::ENTITY_SHIPMENT_ITEM_COLLECTION =>
'\Bitrix\Sale\ShipmentItemCollection',
Registry::ENTITY_SHIPMENT_ITEM_STORE =>
'\Bitrix\Sale\ShipmentItemStore',
Registry::ENTITY_SHIPMENT_ITEM_STORE_COLLECTION =>
'\Bitrix\Sale\ShipmentItemStoreCollection',
Registry::ENTITY_PROPERTY_VALUE_COLLECTION =>
'\Bitrix\Sale\PropertyValueCollection',
Registry::ENTITY_PROPERTY_VALUE =>
'\Bitrix\Sale\PropertyValue',
Registry::ENTITY_PROPERTY =>
'Bitrix\Sale\Property',
Registry::ENTITY_TAX =>
'\Bitrix\Sale\Tax',
Registry::ENTITY_BASKET_PROPERTY_ITEM =>
'\Bitrix\Sale\BasketPropertyItem',
Registry::ENTITY_BUNDLE_COLLECTION =>
'\Bitrix\Sale\BundleCollection',
Registry::ENTITY_BASKET =>
'\Bitrix\Sale\Basket',
Registry::ENTITY_BASKET_ITEM =>
'\Bitrix\Sale\BasketItem',
Registry::ENTITY_BASKET_PROPERTIES_COLLECTION =>
'\Bitrix\Sale\BasketPropertiesCollection',
Registry::ENTITY_DISCOUNT =>
'\Bitrix\Sale\Discount',
Registry::ENTITY_DISCOUNT_COUPON =>
'\Bitrix\Sale\DiscountCouponsManager',
Registry::ENTITY_ORDER_DISCOUNT =>
'\Bitrix\Sale\OrderDiscount',
Registry::ENTITY_OPTIONS =>
'Bitrix\Main\Config\Option',
Registry::ENTITY_PERSON_TYPE =>
'Bitrix\Sale\PersonType',
Registry::ENTITY_ORDER_STATUS =>
'Bitrix\Sale\OrderStatus',
Registry::ENTITY_DELIVERY_STATUS =>
'Bitrix\Sale\DeliveryStatus',
Registry::ENTITY_ENTITY_MARKER =>
'\Bitrix\Sale\EntityMarker',
Registry::ENTITY_ORDER_HISTORY =>
'Bitrix\Sale\OrderHistory',
Registry::ENTITY_NOTIFY =>
'Bitrix\Sale\Notify',
Registry::ENTITY_TRADE_BINDING_COLLECTION =>
'Bitrix\Sale\TradeBindingCollection',
Registry::ENTITY_TRADE_BINDING_ENTITY =>
'Bitrix\Sale\TradeBindingEntity',
Получение класса из реестра:
¶Переопределение класса-обработчика:
Событие для проброса своих классов-обработчиков:
use Bitrix\Main\EventManager;
(EventManager::getInstance())
->addEventHandler(
'main',
'OnInitRegistryList',
[
'\AlexeyGfi\BasketHelper',
'registerCustomInstances'
]
);
В методе \Bitrix\Sale\Registry::initRegistry
результат обработчика будет с-array_merge-н поверх стандартного списка:
Обсуждение статьи