Если вы нашли эту статью, значит вы как и я не смогли решить данную задачи при помощи событий OnAfterIBlockElementUpdate 🙂
Как в битриксе перезаписать цену взятую из свойства
В одной статье сказано, “основная причина почему не работают обработчики событий для элементов связана с тем что сначала выполняются обработчики для инфоблока, а затем для каталога”.
Это значит что наши события при добавлении или обновлении информационных блоков просто отработают первыми, и даже если мы напишем CPrice::Update – то он просто перезапишется значениями из вкладки “торговый каталог”.
Наша задача брать цену из свойства (при добавлении через админ форму, публичную или админ раздела) и перезаписывать значение цены в самом каталоге. Решить данную проблему можно в 2 шага:
Шаг 1: заходим в настройки инфоблока с товарами (Каталог). На первой вкладке ищем поле “Файл для редактирования элемента, позволяющий модифицировать поля перед сохранением:”. Записываем значение:
/bitrix/php_interface/include/iblock_catalog_edit_after_save.php
После сохранения создаем файл на сервере по данному пути.
Шаг 2: В файл iblock_catalog_edit_after_save.php – пишем следующий код:
<? function BXIBlockAfterSave($arFields) { $price = array_shift($_POST['PROP'][55]); // take first value $price = str_replace(',', '.', $price); // replace coma //AddMessage2Log($price); $PRODUCT_ID = $arFields['ID']; $arField = Array( "PRODUCT_ID" => $PRODUCT_ID, "CATALOG_GROUP_ID" => 1, "PRICE" => $price, "CURRENCY" => "RUB" ); $res = CPrice::GetList(array(),array("PRODUCT_ID" => $PRODUCT_ID, "CATALOG_GROUP_ID" => 1)); if ($arr = $res->Fetch()) { CPrice::Update($arr["ID"], $arField); } else { CPrice::Add($arField); } } ?>
А теперь давайте разбираться, тут есть несколько ньюансов:
1. BXIBlockAfterSave – именно это событие и поможет нам справиться с задачей, другие события просто не реагируют..
2. $price = array_shift($_POST[‘PROP’][55]); – в массиве $arFields не так и много полей за которые можно зацепиться (если я не путаю там даже ID информационного блока нет 🙂 ), поэтому мы будем работать с массивом $_POST. Вывести содержимое этого массива можно при помощи:
AddMessage2Log($_POST);
Не забудьте что вам нужно в файле /bitrix/php_interface/dbconn.php прописать путь к лог файлу:
define("LOG_FILENAME", $_SERVER["DOCUMENT_ROOT"]."/.log.txt");
Если вы всё сделали правильно, можете попробовать пересохранить какой-либо элемент каталога (под элементом в данном контексте я имею ввиду товар, но в инфоблоках эта сущность по умолчанию называется элемент).
3. 55 – это ID моего свойства с ценой, которое я изменяю и далее значение которого мы записываем в переменную при помощи:
$price = array_shift($_POST['PROP'][55]); // take first value $price = str_replace(',', '.', $price); // replace coma
Вам нужно изменить 55 на ID вашего свойства. Ну а вторым действием заменяем запятую на точку, чтобы избежать каких-то ошибок.
Далее по коду мы просто вылавливаем ID элемента, и выполняем обновление цены. Если цены нет, то создаем ее. Тут нам помогают CPrice::Update и CPrice::Add.
Внимательный читатель спросит – а зачем же нам init.php? А в том то и дело, что единственное чем нам поможет этот файл, это записать данную функцию туда, вопрос – есть ли в этом смысл? Ведь всё что грузится в init.php доступно потом почти в любой части сайта.
Надеюсь у вас всё получилось, пишите в комментариях о своих успехах 🙂
Здравствуйте. А если товар с предложениями, код будет работать?
Здравствуйте, нет, для торговых предложений код нужно немного дописать
Добрый день. А можно примерчик для ТП? Долго уже бьюсь, не могу заставить работать…
Здравствуйте, для торговых предложений данную задачу нужно решать через обработчик событий OnBeforeIBlockElementAdd или OnBeforeIBlockElementUpdate в файле init.php. Готового примера нет.
Спасибо за данное решение. Подскажите, пожалуйста: этот код успешно работает при добавлении его в указанный файл, но при добавлении в init.php не работает. Хотелось бы, чтобы он срабатывал при обмене сайта с 1С. Чем его дополнить, чтобы он срабатывал в init.php?
Спасибо добрый человек! В моём случае всё свелось к простому:
function BXIBlockAfterSave($arFields) {
CModule::IncludeModule(‘iblock’);
$db_props = CIBlockElement::GetProperty(4, $arFields[‘ID’], [], [“CODE”=>”PRICE”]);
if($arProps = $db_props->Fetch()){
if($arProps[“VALUE”] > 0){
CPrice::SetBasePrice($arFields[‘ID’], $arProps[“VALUE”],”RUB”);
};
}
}
Без этого костыля CPrice::SetBasePrice в init.php упорно выдавал true но ничего не менял, зараза!