Bitrix: Отслеживание изменения свойств элемента инфоблока при помощи обработчика событий

  • 2020-07-21
  • Дмитрий М.
  • 380

Bitrix: Отслеживание изменения свойств элемента инфоблока при помощи обработчика событий

<p> Допустим элемент инфоблока является товаров, у этого элемента инфоблока есть свойство <b>PRICE</b>, в котором хранится значение цены товара. Соответственно при обновлении этого свойства <b>PRICE</b> необходимо автоматически обновлять цену товара (цену которая находится на вкладке <i>Торговый каталог</i>). </p> <p> При изменении элементов инфоблока вызываются события: </p> <p> </p> <ul> <li><b>OnBeforeIBlockElementUpdate </b>- событие, которое вызывается перед изменением элемента.</li> <li><b>OnStartIBlockElementUpdate </b>- событие, которое вызывается в момент начала изменения элемента.</li> <li><b>OnBeforeIBlockElementUpdate </b>- событие, которое вызывается после изменения элемента.</li> </ul> <p> В нашем случаи воспользуемся событием <b>OnBeforeIBlockElementUpdate</b>. Цену будем обновлять при помощи способа указанно в статье <a href="/why-not-updated-the-price-in-bitrix-with-cprice-update/">об обновлении цен при помощи метода CPrice::Update</a>; </p> <p> Полученный обработчик событий необходимо прописать в файле <b>init.php</b><br> </p> <blockquote class="bxhtmled-quote"> Файл init.php храниться в папке <b>/bitrix/php_interface/</b> или <b>/local/php_interface/</b> если его там нет, нужно создать </blockquote> <pre class="line-numbers"><code class="language-php">AddEventHandler("iblock", "OnBeforeIBlockElementUpdate", "UpdateProductPrice"); function UpdateProductPrice($arFields){ $IBLOCK_ID = 1; // Указываем ID инфоблока для элементов которого нужно выполнять действия if ($arFields['IBLOCK_ID'] == $IBLOCK_ID &amp;&amp; !empty($arFields['PROPERTY_VALUE']['PRICE']['VALUE']) &amp;&amp; is_numeric($arFields['PROPERTY_VALUE']['PRICE']['VALUE'])){ $price = $arFields['PROPERTY_VALUE']['PRICE']['VALUE']; $id = $arFields['ID']; $rsFields = Array( "PRODUCT_ID" =&gt; $id, "CATALOG_GROUP_ID" =&gt; 1, // Указываем ID цены, можно посмотреть в админке: Магазин - Настройки - Типы цен "PRICE" =&gt; (int)$price, "CURRENCY" =&gt; "RUB", "QUANTITY_FROM" =&gt; false, "QUANTITY_TO" =&gt; false ); // Добавляем для элемента параметры товара CCatalogProduct::Add( array( "ID" =&gt; $id, "QUANTITY" =&gt; 9999 ) ); //Получаем цены товара ( в том случаи если уже есть цена у товара ), если нет, тогда добавляем сразу цену. $res = CPrice::GetList( array(), array( "PRODUCT_ID" =&gt; $id, "CATALOG_GROUP_ID" =&gt; 1 ) ); if ($arr = $res-&gt;Fetch()) { CPrice::Update($arr["ID"], $rsFields); } else { CPrice::Add($rsFields); } } }</code> </pre> <p> Однако если обновление свойства <b>PRICE </b>осуществляется не при помощи метода <b>CIBlockElement::Update()</b>, а при помощи методов: <b>CIBlockElement::SetPropertyValues</b>, <b>CIBlockElement::SetPropertyValueCode</b>, <b>CIBlockElement::SetPropertyValuesEx</b> - указанные выше обработчики использовать не получится, так как для этих методов работаю свои обработчики событий: </p> <table class="table table-bordered"> <thead class="thead-dark"> <tr> <th scope="col"> Метод </th> <th scope="col"> Обработчик события </th> </tr> </thead> <tbody> <tr> <td> CIBlockElement::SetPropertyValues </td> <td> <ul> <li>OnIBlockElementSetPropertyValues</li> <li>OnAfterIBlockElementSetPropertyValues</li> </ul> </td> </tr> <tr> <td> CIBlockElement::SetPropertyValuesEx </td> <td> <ul> <li>OnIBlockElementSetPropertyValuesEx</li> <li>OnAfterIBlockElementSetPropertyValuesEx</li> </ul> </td> </tr> </tbody> </table> <p> В таком случаи необходимо переписать обработчик события на актуальные события в зависимости от метода изменения свойств элемента. </p> <p> Допустим свойство изменяется при помощи метода <b>CIBlockElement::SetPropertyValues</b>, тогда код будет выглядеть следующим образом: </p> <pre class="line-numbers"><code class="language-php">AddEventHandler("iblock", "OnAfterIBlockElementSetPropertyValues", "UpdateProductPrice"); function UpdateProductPrice($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUES, $PROPERTY_CODE){ $iblockID = 1; // Указываем ID инфоблока для элементов которого нужно выполнять действия if ($IBLOCK_ID == $iblockID &amp;&amp; $PROPERTY_CODE == 'PRICE' &amp;&amp; !empty($PROPERTY_VALUE) &amp;&amp; is_numeric($PROPERTY_VALUE)){ $price = $PROPERTY_VALUE; $id = $ELEMENT_ID; $rsFields = Array( "PRODUCT_ID" =&gt; $id, "CATALOG_GROUP_ID" =&gt; 1, // Указываем ID цены, можно посмотреть в админке: Магазин - Настройки - Типы цен "PRICE" =&gt; (int)$price, "CURRENCY" =&gt; "RUB", "QUANTITY_FROM" =&gt; false, "QUANTITY_TO" =&gt; false ); // Добавляем для элемента параметры товара CCatalogProduct::Add( array( "ID" =&gt; $id, "QUANTITY" =&gt; 9999 ) ); //Получаем цены товара ( в том случаи если уже есть цена у товара ), если нет, тогда добавляем сразу цену. $res = CPrice::GetList( array(), array( "PRODUCT_ID" =&gt; $id, "CATALOG_GROUP_ID" =&gt; 1 ) ); if ($arr = $res-&gt;Fetch()) { CPrice::Update($arr["ID"], $rsFields); } else { CPrice::Add($rsFields); } } }</code> </pre>

22.07.2020 02:06:39

Screenshot_19.png

Screenshot_19.png

Bitrix: Отслеживание изменения свойств элемента инфоблока при помощи обработчика событий

Часто сталкиваюсь с ситуациями когда при обновлении элементов инфоблока необходимо либо обрабатывать данные, которые вводятся или же выполнять какие-то автоматические действия.

Для отслеживания изменений и автоматизации работы в Bitrix есть обработчики событий. Рассмотрим их применение ниже

Допустим элемент инфоблока является товаров, у этого элемента инфоблока есть свойство PRICE, в котором хранится значение цены товара. Соответственно при обновлении этого свойства PRICE необходимо автоматически обновлять цену товара (цену которая находится на вкладке Торговый каталог).

При изменении элементов инфоблока вызываются события:

  • OnBeforeIBlockElementUpdate - событие, которое вызывается перед изменением элемента.
  • OnStartIBlockElementUpdate - событие, которое вызывается в момент начала изменения элемента.
  • OnBeforeIBlockElementUpdate - событие, которое вызывается после изменения элемента.

В нашем случаи воспользуемся событием OnBeforeIBlockElementUpdate. Цену будем обновлять при помощи способа указанно в статье об обновлении цен при помощи метода CPrice::Update;

Полученный обработчик событий необходимо прописать в файле init.php

Файл init.php храниться в папке /bitrix/php_interface/ или /local/php_interface/ если его там нет, нужно создать
AddEventHandler("iblock", "OnBeforeIBlockElementUpdate", "UpdateProductPrice");

function UpdateProductPrice($arFields){
	$IBLOCK_ID = 1; // Указываем ID инфоблока для элементов которого нужно выполнять действия
	if ($arFields['IBLOCK_ID'] == $IBLOCK_ID && !empty($arFields['PROPERTY_VALUE']['PRICE']['VALUE']) && is_numeric($arFields['PROPERTY_VALUE']['PRICE']['VALUE'])){
		$price = $arFields['PROPERTY_VALUE']['PRICE']['VALUE'];
		$id = $arFields['ID'];
		$rsFields = Array(
			"PRODUCT_ID" => $id,
			"CATALOG_GROUP_ID" => 1, // Указываем ID цены, можно посмотреть в админке: Магазин - Настройки - Типы цен
			"PRICE" => (int)$price,
			"CURRENCY" => "RUB",
			"QUANTITY_FROM" => false,
			"QUANTITY_TO" => false
		);
		// Добавляем для элемента параметры товара
		CCatalogProduct::Add(
			array(
				"ID" => $id,
				"QUANTITY" => 9999
			)
		);
		//Получаем цены товара ( в том случаи если уже есть цена у товара ), если нет, тогда добавляем сразу цену.
		$res = CPrice::GetList(
			array(),
			array(
				"PRODUCT_ID" => $id,
				"CATALOG_GROUP_ID" => 1
			)
		);
		if ($arr = $res->Fetch())
		{
			CPrice::Update($arr["ID"], $rsFields);
		}
		else
		{
			CPrice::Add($rsFields);
		}
	}
}

Однако если обновление свойства PRICE осуществляется не при помощи метода CIBlockElement::Update(), а при помощи методов: CIBlockElement::SetPropertyValues, CIBlockElement::SetPropertyValueCode, CIBlockElement::SetPropertyValuesEx - указанные выше обработчики использовать не получится, так как для этих методов работаю свои обработчики событий:

Метод Обработчик события
CIBlockElement::SetPropertyValues
  • OnIBlockElementSetPropertyValues
  • OnAfterIBlockElementSetPropertyValues
CIBlockElement::SetPropertyValuesEx
  • OnIBlockElementSetPropertyValuesEx
  • OnAfterIBlockElementSetPropertyValuesEx

В таком случаи необходимо переписать обработчик события на актуальные события в зависимости от метода изменения свойств элемента.

Допустим свойство изменяется при помощи метода CIBlockElement::SetPropertyValues, тогда код будет выглядеть следующим образом:

AddEventHandler("iblock", "OnAfterIBlockElementSetPropertyValues", "UpdateProductPrice");

function UpdateProductPrice($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUES, $PROPERTY_CODE){
	$iblockID = 1; // Указываем ID инфоблока для элементов которого нужно выполнять действия
	if ($IBLOCK_ID == $iblockID && $PROPERTY_CODE == 'PRICE' && !empty($PROPERTY_VALUE) && is_numeric($PROPERTY_VALUE)){
		$price = $PROPERTY_VALUE;
		$id = $ELEMENT_ID;
		$rsFields = Array(
			"PRODUCT_ID" => $id,
			"CATALOG_GROUP_ID" => 1, // Указываем ID цены, можно посмотреть в админке: Магазин - Настройки - Типы цен
			"PRICE" => (int)$price,
			"CURRENCY" => "RUB",
			"QUANTITY_FROM" => false,
			"QUANTITY_TO" => false
		);
		// Добавляем для элемента параметры товара
		CCatalogProduct::Add(
			array(
				"ID" => $id,
				"QUANTITY" => 9999
			)
		);
		//Получаем цены товара ( в том случаи если уже есть цена у товара ), если нет, тогда добавляем сразу цену.
		$res = CPrice::GetList(
			array(),
			array(
				"PRODUCT_ID" => $id,
				"CATALOG_GROUP_ID" => 1
			)
		);
		if ($arr = $res->Fetch())
		{
			CPrice::Update($arr["ID"], $rsFields);
		}
		else
		{
			CPrice::Add($rsFields);
		}
	}
}


Статья была полезна? Поблагодарите автора.

Возврат к списку

Другие статьи