Контекст проблемы
При попытке настроить поиск по свойству инфоблока типа «Строка» (например, «Артикул») через стандартный чекбокс «Значения свойства участвуют в поиске» результат часто оказывается некорректным. Это связано с тем, что модуль поиска Bitrix не всегда учитывает значения свойств, требующих дополнительной обработки или связанных с API-генерируемыми данными.
Анализ причины
-
Ограничение стандартного функционала:
-
Чекбокс «Значения свойства участвуют в поиске» работает только для свойств, сохраняемых в плоской структуре (например, *`ELEMENTPROPERTY`**).
-
Для свойств, связанных с API (напр., артикулы, генерируемые через
\Bitrix\Iblock\Elements\*) или динамически вычисляемых, требуется ручная индексация.
-
-
Событие
BeforeIndex:-
Позволяет модифицировать данные перед их записью в поисковый индекс.
-
Через него можно добавить значение свойства «Артикул» в поля
TITLEилиBODYиндекса.
-
Решение: Кастомный обработчик для события BeforeIndex
Реализуйте логику принудительной индексации артикула, используя следующий код в файле /local/php_interface/init.php:
<?php
use Bitrix\Main\EventManager;
// Регистрация обработчика события BeforeIndex
EventManager::getInstance()->addEventHandler(
'search',
'BeforeIndex',
['SearchHandlers', 'modifySearchIndex']
);
class SearchHandlers
{
/**
* Модифицирует данные поискового индекса для элементов каталога.
*
* @param array $arFields — массив данных индексации.
* @return array — обновленный массив.
*/
public static function modifySearchIndex(array $arFields): array
{
// ID инфоблока каталога (заменить на актуальный)
$catalogIblockId = 2;
// Символьный код свойства "Артикул"
$articleCode = 'VENDOR_CODE';
// Проверка модуля и инфоблока
if (
$arFields['MODULE_ID'] !== 'iblock'
|| (int)$arFields['PARAM2'] !== $catalogIblockId
) {
return $arFields;
}
// Получение значения свойства "Артикул"
$articleValue = self::getElementPropertyValue(
$arFields['ITEM_ID'],
$articleCode,
$catalogIblockId
);
if ($articleValue) {
// Добавление артикула в заголовок и тело индекса
$arFields['TITLE'] .= " [{$articleValue}]";
$arFields['BODY'] = "{$articleValue} " . $arFields['BODY'];
}
return $arFields;
}
/**
* Возвращает значение свойства элемента.
*
* @param int $elementId — ID элемента.
* @param string $propCode — символьный код свойства.
* @param int $iblockId — ID инфоблока.
* @return string|null — значение свойства.
*/
private static function getElementPropertyValue(int $elementId, string $propCode, int $iblockId): ?string
{
\Bitrix\Main\Loader::includeModule('iblock');
$property = \CIBlockElement::GetProperty(
$iblockId,
$elementId,
[],
['CODE' => $propCode]
)->Fetch();
return $property['VALUE'] ?? null;
}
}
Или
use \Bitrix\Main\EventManager;
$eventManagerInstance = EventManager::getInstance();
$eventManagerInstance->addEventHandler(
"search",
"BeforeIndex",
[
"Handlers",
"beforeIndex"
]
);
class Handlers
{
public static function beforeIndex($arFields)
{
if (!$arFields["MODULE_ID"] == "iblock" && $arFields['PARAM2'] == CATALOG_IBLOCK_ID) {
return $arFields;
}
\Bitrix\Main\Loader::includeModule('iblock');
$product = \Bitrix\Iblock\Elements\ElementCatalogTable::getByPrimary($arFields['ITEM_ID'], [
'select' => ['ID', 'SKU' => 'VENDOR_CODE.VALUE'],
])->fetch();
$arFields['TITLE'] .= ' ['.$product['SKU'].']';
return $arFields;
}
}
Критические замечания
-
Переиндексация:
- После внедрения кода выполните полную переиндексацию.
-
Оптимизация запросов:
- Для инфоблоков с большим количеством элементов используйте кеширование.
-
Обработка ошибок:
- Опционально можно добавить проверку существования элемента и свойства:
if (!\CIBlockElement::GetByID($elementId)->Fetch()) {
return null;
}
Заключение Предложенное решение обходит ограничения стандартного поиска Bitrix, гарантируя корректную индексацию свойств типа «Строка». Метод поддерживает гибкую настройку и может быть адаптирован для любых пользовательских свойств, включая артикулы, серийные номера и другие идентификаторы.