Поиск товара по XML_ID (События Битрикс)

В данной заметке рассматривается вопрос о том, как реализовать в битриксе поиск товаров по внешнему коду (XML_ID). Стоит сразу оговориться, что для высоконагруженных проектов данное решение не подходит — так как при пиковых нагрузках поиск начинает вести себя аномально.

Иногда возникает потребность расширить функционал стандартного поиска по сайту. Одним из возможных «расширений» может быть добавление возможности поиска товара по внешнему коду (Поле XML_ID в таблице b_iblock_element). По умолчанию поиск битрикса не умеет искать по этому полю. Поэтому есть два возможных пути, которые приведут к этой цели:

  • Записывать автоматом внешний код в поле теги (если, конечно, поиск по этому полю осуществляется)
  • Создать отдельное свойство инфоблока и записывать код в него.

Особой разницы, в общем-то, нет. Ниже рассматривается первый вариант.

Итак, каков общий алгоритм решения данной задачи?

  • В файл intit.php мы добавляем обработчик события OnAfterIBlockElementUpdate. Это событие, которое срабатывает после попытки изменения элемента.
  • Внутри нашего класса UpdateElement прописываем строку public static $disableHandler = false;. Иначе обработчик уйдет в бесконечный цикл.
  • Далее подключаем функцию, которая будет обновлять элемент. if( $arFields[«IBLOCK_ID»] == «5») — данный if ограничивает событие только инфоблоком под номером 5
  • Строка $arLoadProductArray = Array( «TAGS» => $arFields[‘XML_ID’] ); — присваивает значение внешнего кода полю «теги».

В целом, на этом всё. Ниже вы можете увидеть полный код события:

AddEventHandler("iblock", "OnAfterIBlockElementUpdate", Array("UpdateElement", "Update"));
	class UpdateElement
	{
		//Чтобы у нас не было 504 ошибки необходимо прописать этот код, он не дает зациклится нашему скрипту
		public static $disableHandler = false;
		 
		function Update(&$arFields)
		{ 
			if (self::$disableHandler)
				return;
				
			CModule::IncludeModule("iblock");
			
			//Обновляем только элементы из определенного инфоблока
			if( $arFields["IBLOCK_ID"] == "5")
			{

				$el = new CIBlockElement;
				
				$arLoadProductArray = Array(
					"TAGS" => $arFields['XML_ID']
				);
				
				self::$disableHandler = true; //отключаем
				if($res = $el->Update($arFields["ID"], $arLoadProductArray))
				 
				{
					//Здесь может быть ваш код, echo написанное здесь выводится не будет
					//echo 'Обновление завершено';
				}
	 
			}
			 
		}
	}

В заключение, стоит еще раз заметить, что данное решение не подходит для высоконагруженных сайтов. Данное событие, рано или поздно, начнет «подвешивать» сайт. Поисковый индекс также начнет работать некорректно. Однако, на маленьких сайтах — всё ок.