Здравствуйте. Стоит у меня одна задача, в процессе которой мне пришлось отказаться от использования старого доброго 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().