Здравствуйте. Стоит у меня одна задача, в процессе которой мне пришлось отказаться от использования старого доброго Add2BasketByProductID дабы иметь возможность повесить свой PRODUCT_PROVIDER_CLASS на товары, добавляемые в корзину.
Простое добавление в корзину работало прекрасно. Но при добавлении свойств начались проблемы. В итоге вышло вот что:
Понятное дело, что это не весь файл, но суть не в этом. Моя проблема была в том, что я пытался добавить свойства к созданному товару до сохранения корзины. Не надо так. До того, как вы сделаете $basket->save() у свежесозданного товара нет ID. Точнее ID=0. То есть, если сделать так:
Свойства привяжутся к товару с ID=0, после сохранения товару присвоится его настоящий ID в корзине, а привязка останется к 0. А с таким порядком действий, как в верхнем примере будет каждый раз искаться товар с заданными свойствами, а так как такого нет, будет создаваться новый.
Поэтому: сначала $basket->save(), а только после этого $basketPropertyCollection->setProperty().
Надеюсь кому-то это пригодиться.
P.S. Ещё стоит небольшое внимание обратить на вот это
Если проигнорировать второе условие, то в случае если никакого свойства не выбрано (а значений у этого свойства много больше, чем можно выбрать, так что есть смысл и пустым оставить, а потом в комментариях прописать отдельно), товар будет добавляться с пустым свойством к первому попавшемуся товару в корзине с таким же $productId и заполненным свойством. Это чуть более очевидно, чем всё остальное, но всё-таки достойно упоминания.
UPD. Как правильно заметил Евгений Микулич в комментариях, необязательно отдельно сохранять свойства. Можно добавить их до сохранения корзины и просто не делать $basketPropertyCollection->save().
Простое добавление в корзину работало прекрасно. Но при добавлении свойств начались проблемы. В итоге вышло вот что:
use Bitrix\Sale,
Bitrix\Main\Application;
$request = Application::getInstance()->getContext()->getRequest();
$basket = Sale\Basket::loadItemsForFUser(Sale\Fuser::getId(), Bitrix\Main\Context::getCurrent()->getSite());
$productId = intval($request->getPost("id"));
$quantity = intval($request->getPost("quantity"));
$properties = array();
if(null !== $request->getPost("color") && '' !== $request->getPost("color")){
$properties['COLOR'] = array(
'NAME' => 'Цвет',
'CODE' => 'COLOR',
'VALUE' => $request->getPost("color"),
'SORT' => 100
);
}
if ($item = $basket->getExistsItem('catalog', $productId, $properties)) {
$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' => 'CCatalogProductProviderCustom',
));
}
$basket->save(); //сохраняем изменения в корзине
if(isset($properties)) {
$basketPropertyCollection = $item->getPropertyCollection();
$basketPropertyCollection->setProperty($properties);
$basketPropertyCollection->save();
} |
Понятное дело, что это не весь файл, но суть не в этом. Моя проблема была в том, что я пытался добавить свойства к созданному товару до сохранения корзины. Не надо так. До того, как вы сделаете $basket->save() у свежесозданного товара нет ID. Точнее ID=0. То есть, если сделать так:
$item = $basket->createItem('catalog', $productId); //создаём новый товар в корзине
$item->setFields(array(
'QUANTITY' => $quantity,
'CURRENCY' => Bitrix\Currency\CurrencyManager::getBaseCurrency(),
'LID' => Bitrix\Main\Context::getCurrent()->getSite(),
'PRODUCT_PROVIDER_CLASS' => 'CCatalogProductProviderCustom',
));
$basketPropertyCollection = $item->getPropertyCollection();
$basketPropertyCollection->setProperty($properties);
$basketPropertyCollection->save(); // сохранение свойств
$basket->save(); //сохраняем изменения в корзине
|
Свойства привяжутся к товару с ID=0, после сохранения товару присвоится его настоящий ID в корзине, а привязка останется к 0. А с таким порядком действий, как в верхнем примере будет каждый раз искаться товар с заданными свойствами, а так как такого нет, будет создаваться новый.
Поэтому: сначала $basket->save(), а только после этого $basketPropertyCollection->setProperty().
Надеюсь кому-то это пригодиться.
P.S. Ещё стоит небольшое внимание обратить на вот это
if(null !== $request->getPost("color") && '' !== $request->getPost("color")) |
UPD. Как правильно заметил Евгений Микулич в комментариях, необязательно отдельно сохранять свойства. Можно добавить их до сохранения корзины и просто не делать $basketPropertyCollection->save().