1C-Битрикс изменить цену при добавлении или обновлении элемента (init.php)

Если вы нашли эту статью, значит вы как и я не смогли решить данную задачи при помощи событий 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 доступно потом почти в любой части сайта.

Надеюсь у вас всё получилось, пишите в комментариях о своих успехах 🙂

Если вам необходимо выполнить работу по различным событиям на вашем битрикс сайте, обращайтесь ко мне за помощью.

автор: Dmitriy

З 2011 року займаюся веб-розробкою. Зараз я – PHP Full Stack Developer.
Обговорити ваш проект, а також дізнатися більше про мене ви можете на цьому сайті:
dev.forwww.com

Email: dmitriyribka@gmail.com

6 коментаря

        1. Здравствуйте, для торговых предложений данную задачу нужно решать через обработчик событий OnBeforeIBlockElementAdd или OnBeforeIBlockElementUpdate в файле init.php. Готового примера нет.

  1. Спасибо за данное решение. Подскажите, пожалуйста: этот код успешно работает при добавлении его в указанный файл, но при добавлении в init.php не работает. Хотелось бы, чтобы он срабатывал при обмене сайта с 1С. Чем его дополнить, чтобы он срабатывал в init.php?

  2. Спасибо добрый человек! В моём случае всё свелось к простому:

    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 но ничего не менял, зараза!

Залишити коментар до Dmitriy Скасувати коментар