Работа с элементами инфоблока, товароми, торговыми предложениями
Товар
добавляется самый обычный простой товар, без каких-либо дополнительных возможностей. Это тот тип товара, который наиболее употребим, и используется в данный момент повсеместно.
Торговые предложения
Данный товар (как товар хранящий список предложений) не имеет остатков, не имеет цены и других атрибутов, которые есть у обычного товара. Этот товар не является товаром. По сути, он содержит список «торговых предложений», которые и являются товарами (предложениями).
Набор
это список привязанных к основному товару товаров, которые магазин хочет порекомендовать к покупке. В набор могут быть добавлены именно товары: торговые предложения и/или простые товары. Товар с торговыми предложениями добавить в него нельзя.
Комплект
это список товаров, составляющих необходимую комплектацию основного товара. Сам комплект не имеет физического остатка, его остаток зависит от товаров, которые входят в этот комплект. В комплект могут быть добавлены именно товары: торговые предложения и/или простые товары. Товар с торговыми предложениями добавить в него нельзя.
Работа с элементами инфоблоков
Добавление элемента инфоблока на сайт:
// инициализируем соответствующий модуль
CModule::IncludeModule("iblock");
// массив со свойствами элемента инфоблока, где ключами массива служат id нужного свойства (но можно использовать параметр CODE). Так же нужно помнить, что для списков и полей с привязкой к элементам или справочникам в качестве значения мы указываем id элемента списка, справочника или объекта
$PROP = array(
'342'=>'',
'315'=>''
);
// создаем объект класса для работы
$el = new CIBlockElement;
// заполняем массив с данными
$arLoadProductArray = Array(
// указываем ID пользователя
"MODIFIED_BY" => 1,
// для привязки ко многим разделам
"IBLOCK_SECTION" => $IBLOCK_SECTION_ID,
// для одиночного раздела
//"IBLOCK_SECTION_ID" => $IBLOCK_SECTION_ID,
"IBLOCK_ID" => 20,
"IBLOCK_TYPE" => 'aspro_next_catalog',
"PROPERTY_VALUES" => $PROP,
"NAME" => $NAME,
"ACTIVE" => "Y",
"CODE" => $CODE,
//"PREVIEW_TEXT" => "текст для списка элементов",
//"DETAIL_TEXT" => "текст для детального просмотра",
//"DETAIL_PICTURE" => CFile::MakeFileArray($_SERVER["DOCUMENT_ROOT"]."/image.gif")
);
$res = $el->Add($arLoadProductArray);
if($res>0) {
// успешно добавили, в $res хранится id добавленной записи
} else {
// добавить не удалось, выводим сообщение с ошибкой
echo $el->LAST_ERROR;
}
Превращаем элемент инфоблока в товар:
/* Делаем добавленный товар простым */
$productFileds = array(
// ID добавленного элемента инфоблока
"ID" => $res,
// выставляем тип ндс (задается в админке)
"VAT_ID" => 1,
// НДС входит в стоимость
"VAT_INCLUDED" => "Y",
// тип товара
"TYPE " => \Bitrix\Catalog\ProductTable::TYPE_PRODUCT
);
// возможные значения типа товара:
//const TYPE_PRODUCT = 1;
//const TYPE_SET = 2;
//const TYPE_SKU = 3;
//const TYPE_OFFER = 4;
//const TYPE_FREE_OFFER = 5;
//const TYPE_EMPTY_SKU = 6;
if(CCatalogProduct::Add($productFileds)) {
// элемент инфоблока превращен в товар
} else {
// произошла ошибка
}
Получение списка свойств элемента инфоблока с помощью D7:
$res = \Bitrix\Iblock\ElementTable::getList(array(
"select" => array("ID", "*"),
"filter" => array("IBLOCK_ID" => $IBLOCK_ID, "ID" => $ELEMENT_ID),
"order" => array("ID" => "ASC")
));
while ($arItem = $res->fetch()) {
$propRes = \Bitrix\Iblock\ElementPropertyTable::getList(array(
"select" => array("ID", "*"),
"filter" => array("IBLOCK_ELEMENT_ID" => $arItem["ID"],),
"order" => array("ID" => "ASC")
));
while($prop = $propRes->Fetch())
$arItem["PROPERTIES"][$prop["IBLOCK_PROPERTY_ID"]] = $prop;
}
Битрикс получить ID элемента по его символьному коду:
CIBlockFindTools::GetElementID($ELEMENT_ID, $ELEMENT_CODE, $SECTION_ID, $SECTION_CODE, $arFilter)
// $section_id - ID секции в которой лежит элемент
// $section_code - символьный код секции в которой лежит элемент
// $arFilter - массив дополнительных свойств для фильтрации
// пример использования
$objFindTools = new CIBlockFindTools();
$elementID = $objFindTools->GetElementID(false, "super_element", false, "super_section", array("IBLOCK_ID" => 1));
// метод возвращает ID элемента, если найдет его, и 0, если элемент не будет найден.
Работа с торговым каталогом
Получаем список типов цен с помощью d7:
$rsPrices = \Bitrix\Catalog\GroupTable::getList();
while($arPrice = $rsPrices->fetch()){
$PRICE_IDS[] = $arPrice['ID'];
}
Получаем цену и кол-во товара с помощью D7:
$dbPrice = \Bitrix\Catalog\Model\Price::getList([
"filter" => array(
"PRODUCT_ID" => $id,
"CATALOG_GROUP_ID" => 1
)]);
if ($arPrice = $dbPrice->fetch()) {
$price = $arPrice['PRICE'];
}
Добавляем или обновляем цену товара:
$arFieldsPrice = array(
// ID добавленного товара
"PRODUCT_ID" => $ID,
// ID типа цены
"CATALOG_GROUP_ID" => 1,
// значение цены
"PRICE" => $item['price'],
// валюта
"CURRENCY" => !$currency ? "RUB" : $currency,
);
// смотрим установлена ли цена адля данного товара
$dbPrice = \Bitrix\Catalog\Model\Price::getList([
"filter" => array(
"PRODUCT_ID" => $item['ID'],
"CATALOG_GROUP_ID" => 1
)
]);
if ($arPrice = $dbPrice->fetch()) {
// если цена установлена, то обновляем
$result = \Bitrix\Catalog\Model\Price::update($arPrice["ID"], $arFieldsPrice);
if ($result->isSuccess()) {
echo "Обновили цену у товара у элемента каталога " . $item['ID'] . " Цена " . $item['price'] . PHP_EOL;
} else {
echo "Ошибка обновления цены у товара у элемента каталога " . $item['ID'] . " Ошибка " . $result->getErrorMessages() . PHP_EOL;
}
} else {
// если цены нет, то добавляем
$result = \Bitrix\Catalog\Model\Price::add($arFieldsPrice);
if ($result->isSuccess()) {
echo "Добавили цену у товара у элемента каталога " . $item['ID'] . " Цена " . $item['price'] . PHP_EOL;
} else {
echo "Ошибка добавления цены у товара у элемента каталога " . $item['ID'] . " Ошибка " . $result->getErrorMessages() . PHP_EOL;
}
}
Добавляем к товару количество на складах:
$arFields = Array(
// ID товара
"PRODUCT_ID" => $id,
// ID склада
"STORE_ID" => $storeId,
// количество
"AMOUNT" => $amount,
);
CCatalogStoreProduct::Add($arFields);
Обновляем кол-во товара на складах:
$rs = CCatalogStoreProduct::GetList(false, array(
// ID товара
'PRODUCT_ID'=> $id,
// ID склада
'STORE_ID' => $storeId
));
while($ar_fields = $rs->GetNext())
{
// обновим значение остатка на складе из значения остатка количественного учёта
$arFields = Array(
// ID товара
"PRODUCT_ID" => $id,
// ID склада
"STORE_ID" => $storeId,
// количество
"AMOUNT" => $amount,
);
CCatalogStoreProduct::Update($ar_fields['ID'], $arFields);
}
Обновление остатков товаров с помощью D7:
$existProduct = \Bitrix\Catalog\Model\Product::getCacheItem($arFields['ID'],true);
if(!empty($existProduct)){
\Bitrix\Catalog\Model\Product::update(intval($arFields['ID']),$arFields);
} else {
\Bitrix\Catalog\Model\Product::add($arFields);
}
Добавляем или обновляем общее кол-во товара, параметр "Доступное кол-во":
CCatalogProduct::Update(
// ID добавленного или обновляемого товара
$ID,
array(
// кол-во товара
"QUANTITY" => $amount,
)
)
Добавляем товар в резерв:
$provider = new \Bitrix\Catalog\Product\CatalogProvider;
$resReserve = $provider->reserve(array(
$productId => ["PRODUCT_ID" => $PRODUCT_ID, "QUANTITY" => 10]
));
Снятие резерва:
$provider = new \Bitrix\Catalog\Product\CatalogProvider;
$resReserve = $provider->reserve(array(
$productId => ["PRODUCT_ID" => $PRODUCT_ID, "QUANTITY" => -10 ]
));
Работа со свойствами товаров
Получаем значение отдельного свойства товара в Битрикс с помощью D7:
class Product
{
private $id;
public function __construct($id)
{
if (empty($id)) {
throw new \Bitrix\Main\ArgumentNullException('id');
}
$this->id = $id;
}
public function getFields()
{
return \Bitrix\Iblock\ElementTable::getById($this->id)->fetch();
}
public function getProperty($code)
{
$fields = $this->getFields();
if ($fields) {
$iblock = \Bitrix\Iblock\Iblock::wakeUp($fields['IBLOCK_ID']);
$element = $iblock->getEntityDataClass()::getByPrimary($this->id, ['select' => [$code]])->fetchObject();
$property = $element->__call('get', [$code]);
}
return $property ? $property->getValue() : null;
}
}
Обновить свойство у элемента по коду свойства и ID элемента:
\CIBlockElement::SetPropertyValuesEx(PRODUCT_ID, false, array('PROPERTY_CODE' => $NEW_PROPERTY_VALUE));
Очистить значение множественного свойства:
\CIBlockElement::SetPropertyValuesEx(PRODUCT_ID, false, ['PROPERTY_CODE' => [0 => ["VALUE" => "" , "DESCRIPTION" => ""]]]);
Получаем значение отдельного свойства товара или ТП, старый способ:
$arFilter = Array("IBLOCK_ID"=>$kitOffer['IBLOCK_ID'], "ID"=>$kitOffer['ID']);
$arSelect = Array("SORT");
$res = CIBlockElement::GetList(Array(), $arFilter,false,false,$arSelect);
if ($ob = $res->GetNextElement()){;
$arFields = $ob->GetFields();
}
Получаем товары в Битрикс с помощью D7:
// фильтр стандартный, вы знаете как им пользоваться
$elementIterator = \Bitrix\Iblock\ElementTable::getList([
'select' => [
'ID',
],
'filter' => [
'=IBLOCK_ID' => 20,
'!=ID' => array(1,2,3),// массив ID товаров которые нужно пропустить
]
]);
$elems = $elementIterator->fetchAll();
foreach ($elems as $element) {
// создаем объект класса для работы
$obElement = new CIBlockElement();
// обновляем элемент и делаем неактивным
$obElement->Update($element['ID'], Array("ACTIVE" => 'N'));
}
Получаем все свойства элемента инфоблока:
CIBlockElement::GetByID($arResult['ID'])->GetNextElement()->GetProperties()
Вывод всех свойств товара:
CCatalogProduct::GetByIDEx($arElement['ID'])
Получаем значения свойства товара типа список:
$property_enums = CIBlockPropertyEnum::GetList(Array("DEF"=>"DESC", "SORT"=>"ASC"), Array("IBLOCK_ID"=>15, "CODE"=>"BREND_INTERNAL"));
while($enum_fields = $property_enums->GetNext()){
echo $enum_fields["ID"]." - ".$enum_fields["VALUE"]."<br>";
}
Добавить новое значение в свойство типа список:
$ibpenum = new CIBlockPropertyEnum;
if($PropID = $ibpenum->Add(Array('PROPERTY_ID'=>$PROPERTY_ID, 'VALUE'=>'New Enum 1')))
echo 'New ID:'.$PropID;
Добавить новое значение в свойство типа список с помощью D7:
\Bitrix\Main\Loader::includeModule('iblock');
$property = \CIBlockProperty::GetList(
[],
[
'IBLOCK_ID' => $iblockId,
'CODE' => $code'
]
)->Fetch();
$ibpenum = new \CIBlockPropertyEnum();
$valueId = $ibpenum->Add([
'PROPERTY_ID' => $property['ID'],
'VALUE' => $newValueText,
'XML_ID' => $newValueXmlId,
]);
if ((int) $valueId < 0) {
throw new \Exception('Unable to add a value');
}
Удалить значение из свойства типа список:
CIBlockPropertyEnum::Delete(ID);
Удалить значение из свойства типа список с помощью D7:
if (! \Bitrix\Main\Loader::includeModule('iblock')) {
throw new \Bitrix\Main\LoaderException('Unable to load IBLOCK module');
}
$property = \CIBlockProperty::GetList([], ['IBLOCK_ID' => $iblockId, 'CODE' => $propertyCode])->Fetch();
if (! $property) {
throw new \Exception('No such property');
}
$query = \CIBlockPropertyEnum::GetList(
[],
["IBLOCK_ID" => $iblockId, "XML_ID" => 6, "PROPERTY_ID" => $property['ID']]
);
$value = $query->GetNext();
if (! $value) {
throw new \Exception('No such value');
}
$delete = \CIBlockPropertyEnum::delete($value['ID']);
if (! $delete) {
throw new \Exception('Error while deleting the property value');
}
Работа с наборами и комплектами
Получаем состав наборов и комплектов для родительского товара:
$arProducts = CCatalogProductSet::GetList(
array(), array( "TYPE" => array(1,2), "OWNER_ID" => $productID), false, false, array()
);
while($item = $arSets->Fetch() ){
if($item["OWNER_ID"]!=$item["ITEM_ID"] ){
$arComplects[] = $item["ITEM_ID"];
}
}
Получаем товары соседствующие с искомым в наборе или комплекте:
\Bitrix\Main\Loader::includeModule('catalog');
$rItems = CCatalogProductSet::GetList(
array(),
array(
array(
'LOGIC' => 'OR',
'TYPE' => CCatalogProductSet::TYPE_GROUP,
'TYPE' => CCatalogProductSet::TYPE_SET
),
'ITEM_ID' => $arResult['ID']),
false,
false,
array('SET_ID', 'OWNER_ID', 'ITEM_ID', 'TYPE')
);
while ($item = $rItems->Fetch()) {
$arComplect[] = $item;
}
Получаем нужные свойства по массиву id торговых предложений:
function getInform($arrOffersIDs){
$arrProductsIDs = array();
foreach($arrOffersIDs as $intElementID){
$mxResult = CCatalogSku::GetProductInfo(
$intElementID, 4
);
if (is_array($mxResult))
{
$arrProductsIDs[] = $mxResult["ID"];
}
}
return CCatalogSKU::getOffersList(
$arrProductsIDs,
$iblockID = 4,
$skuFilter = array('ID'=>$arrOffersIDs),
$fields = array('ID','NAME','DETAIL_PICTURE'),
$propertyFilter = array() );
}
print_r(getInform(array(45,87,98)));
Получаем нужные свойства всех торговых предложений:
function getInform($arrOffersIDs){
$arrProductsIDs = array();
foreach($arrOffersIDs as $intElementID){
$mxResult = CCatalogSku::GetProductInfo(
$intElementID,
4 //ID каталога с товаром
);
if (is_array($mxResult))
{
$arrProductsIDs[] = $mxResult["ID"];
}
}
return CCatalogSKU::getOffersList(
$arrProductsIDs,
$iblockID = 4, //ID каталога с товаром
$skuFilter = array(),
$fields = array('NAME','ID','DETAIL_PICTURE','PREVIEW_PICTURE', "DETAIL_PAGE_URL", "CML2_MANUFACTURER", "DETAIL_TEXT"),//Получаемые свойства
$propertyFilter = array() );
}
print_r(getInform(array(45,87,98)));
Работа со скидками
Получаем скидки и правила работы с корзиной, которые были применены к товару. В файле result_modifier.php
компонента sale.basket.basket
получаем перечень примененных к товару скидок:
/** @var \Bitrix\Sale\BasketBase $basket */
$basket = (\Bitrix\Sale\Basket\Storage::getInstance(
\Bitrix\Sale\Fuser::getId(),
\Bitrix\Main\Context::getCurrent()->getSite()))
->getOrderableBasket();
$order = $basket->getOrder();
$discountApplyResults = $order->getDiscount()->getApplyResult(false);
Автогенерации правила работы с корзиной, добавление купона и его применение.
Код генерации:
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
use Bitrix\Sale\Internals;
CModule::IncludeModule("catalog");
CModule::IncludeModule("iblock");
CModule::IncludeModule("sale");
global $APPLICATION;
$unixStart = strtotime(date("d.m.Y H:i:s"));
// 12 часов
$unixEnd = $unixStart+43200;
$xcount = 0;
// размер случайной скидки от 1 до 10 процентов
$discountValue = rand(1,10);
$Actions["CLASS_ID"] = "CondGroup";
$Actions["DATA"]["All"] = "AND";
$Actions["CLASS_ID"] = "CondGroup";
$Actions["CHILDREN"][0]["CLASS_ID"] = "ActSaleBsktGrp";
$Actions["CHILDREN"][0]["DATA"]["Type"] = "Discount";
$Actions["CHILDREN"][0]["DATA"]["Value"] = $discountValue;
$Actions["CHILDREN"][0]["DATA"]["Unit"] = "Perc";
$Actions["CHILDREN"][0]["DATA"]["All"] = "OR";
$DbParentEl = CIBlockElement::GetList(array(),array("SECTION_ID"=>array(10,11)),false,false,array("ID"));
while($ParentId = $DbParentEl->Fetch()){
//Массив товаров к которым будет применяться скидка
$Actions["CHILDREN"][0]["CHILDREN"][$xcount]["CLASS_ID"] = "CondIBElement";
$Actions["CHILDREN"][0]["CHILDREN"][$xcount]["DATA"]["logic"] = "Equal";
$Actions["CHILDREN"][0]["CHILDREN"][$xcount]["DATA"]["value"] = $ParentId["ID"];
$xcount++;
}
$Conditions["CLASS_ID"] = "CondGroup";
$Conditions["DATA"]["All"] = "AND";
$Conditions["DATA"]["True"] = "True";
$Conditions["CHILDREN"] = "";
// массив для создания правила
$arFields = array(
"LID"=>"s1",
"NAME"=>$discountValue."% Скидки ".date("d.m.y"),
"CURRENCY"=>"RUB",
"ACTIVE"=>"Y",
"USER_GROUPS"=>array(1),
"ACTIVE_FROM"=>ConvertTimeStamp($unixStart, "FULL"),
"ACTIVE_TO"=>ConvertTimeStamp($unixEnd, "FULL"),
"CONDITIONS"=>$Conditions,
'ACTIONS' => $Actions
);
// создаем правило корзины
$ID = CSaleDiscount::Add($arFields);
$res = $ID>0;
if ($res) {
// генирация купона
$codeCoupon = CatalogGenerateCoupon();
$fields["DISCOUNT_ID"] = $ID;
$fields["COUPON"] = $codeCoupon;
$fields["ACTIVE"] = "Y";
$fields["TYPE"] = 2;
$fields["MAX_USE"] = 0;
// создаем купон для этого правила
$dd = Internals\DiscountCouponTable::add($fields);
if (!$dd->isSuccess())
{
$err = $dd->getErrorMessages();
}else{
echo 'Купон на скидку: '.$codeCoupon;
}
}else{
$ex = $APPLICATION->GetException();
echo 'Ошибка: '.$ex->GetString();
}
Код вызова:
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
use Bitrix\Main\Loader;
use Bitrix\Sale\DiscountCouponsManager;
CModule::IncludeModule("sale");
$check = DiscountCouponsManager::isExist($_POST['coupon']);
if($check["ID"]>0){
DiscountCouponsManager::add($_POST['coupon']);
echo "ok";
}else{
echo 'Такого купона не существует';
}