Если вам по какой-то причине нужно скопировать цену товара в свойство этого же инфоблока. Например, для вывода старой цены в редакции Битрикс "Малый бизнес" (цена товара за минусом какого-то процента). Можно воспользоваться данной заметкой.
Итак: у нас есть инфоблок торгового каталога, в котором мы хотим заполнить свойство типа число (или строка) стоимостью элемента. В моем случае, код этого свойства "ATT_PRICE"
Единоразовое заполнение или по необходимости
Если нужно выполнить заполнение один раз или в ручную, по необходимости.
Создаем новую страничку на сайте (можно ограничить к ней доступ, только для администраторов) и вставляем туда такой код, подсказки по коду, прямо внутри:
CModule::IncludeModule('iblock');
CModule::IncludeModule('catalog');
CModule::IncludeModule('currency');
$IBLOCK_ID = 34; //Инфоблок с которым работаем
//Получаем ID всех элементов
$addProps = CIBlockElement::GetList (
Array("ID" => "ASC"),
Array("IBLOCK_ID" => $IBLOCK_ID),
false,
false,
Array(
'ID'
)
);
while($ar_fields = $addProps->GetNext())
{
$arProductID = $ar_fields['ID'];
//Узнаем цену элемента
$rsPrices = CPrice::GetList(
array(),
array(
"PRODUCT_ID" => $arProductID,
)
);
while($arPrice = $rsPrices->Fetch())
//Передаем цену в переменную
{
$PropPrice = $arPrice["PRICE"];
}
//Заполняем свойство с кодом "ATT_PRICE" ценой
CIBlockElement::SetPropertyValuesEx(
$arProductID,
$IBLOCK_ID,
array(
"ATT_PRICE" => $PropPrice,
)
);
}
Сохраняем и открываем в браузере. Скрипт отработает и у всех товаров заполнится свойство ATT_PRICE. Учтите, что если у вас большой каталог, это может занять некоторое время. Если каталог очень большой, убедитесь что работа не завершится по таймауту. Я пробовал на каталоге с 50 000-ами товаров. Код отработал за 12 секунд
Далее, можете выполнять этот код в ручную или повесить выполнение на крон.
Постоянная работа скрипта. Обработчик в init.php
Если вам нужно, что бы свойство ATT_PRICE обновлялось постоянно, при каждом добавлении товаров и обновлении цен. Например, при обмене с 1С
Можете добавить обработчик в init.php. Код основан на томже, что приведен выше, в принципе выполняет теже самые действия по событиям обновления/добавления элементов
AddEventHandler("iblock", "OnAfterIBlockElementUpdate", "DoIBlockAfterSave");
AddEventHandler("iblock", "OnAfterIBlockElementAdd", "DoIBlockAfterSave");
AddEventHandler("catalog", "OnPriceAdd", "DoIBlockAfterSave");
AddEventHandler("catalog", "OnPriceUpdate", "DoIBlockAfterSave");
function DoIBlockAfterSave($arg1, $arg2 = false) {
CModule::IncludeModule('iblock');
CModule::IncludeModule('catalog');
CModule::IncludeModule('currency');
$IBLOCK_ID = 34;
$ELEMENT_ID = null;
if (is_array($arg2) && isset($arg2["PRODUCT_ID"]) && $arg2["PRODUCT_ID"] > 0) {
$ELEMENT_ID = $arg2["PRODUCT_ID"];
} elseif (is_array($arg1) && isset($arg1["ID"]) && $arg1["ID"] > 0) {
$arElementFields = CIBlockElement::GetByID($arg1["ID"])->GetNext();
if (in_array($arElementFields["IBLOCK_ID"], array($IBLOCK_ID))) {
$ELEMENT_ID = $arg1["ID"];
}
}
if ($ELEMENT_ID) {
$arProductID = array($ELEMENT_ID);
$rsProperty = CIBlockProperty::GetByID("PRICE", $IBLOCK_ID);
if ($arProperty = $rsProperty->Fetch()) {
$arPropCache[$IBLOCK_ID] = $arProperty["ID"];
} else {
// Обработка ситуации, если свойство PRICE не найдено
return;
}
$rsPrices = CPrice::GetList(
array(),
array(
"PRODUCT_ID" => $arProductID,
)
);
$PropPrice = null;
while ($arPrice = $rsPrices->Fetch()) {
$PRICE = $arPrice["PRICE"];
$PropPrice = $PRICE; // Если нужно агрегировать цены, изменить логику здесь
}
if ($PropPrice !== null) {
CIBlockElement::SetPropertyValuesEx(
$ELEMENT_ID,
$IBLOCK_ID,
array(
"ATT_PRICE" => $PropPrice,
)
);
}
}
}
Полезные дополнения:
Если хотите сконвертировать цену в другую валюту. Например: цена в каталоге указана в долларах, а в свойство должна попасть в рублях по курсу модуля валют.
Воспользуйтесь методом CCurrencyRates::ConvertCurrency в части получения цены товара
$strDefaultCurrency = CCurrency::GetBaseCurrency();
$arPrice["PRICE"] = CCurrencyRates::ConvertCurrency($arPrice["PRICE"], $arPrice["CURRENCY"], $strDefaultCurrency);
$PRICE = $arPrice["PRICE"];
$PropPrice = $PRICE;
Если нужно получить больше информации о свойстве ATT_PRICE. Например получить ее ID, проверить на заполненность итд. Воспользуйтесь методом CIBlockProperty::GetByID:
$rsProperty = CIBlockProperty::GetByID("ATT_PRICE", $IBLOCK_ID);
$arProperty = $rsProperty->Fetch();
$arPropCache[$IBLOCK_ID] = $arProperty["ID"];