Автоматизация
Внедрение битрикс24 бесплатно
При покупке лицензии у меня
Подробнее
Битрикс24
Для новых клиентов -30%
На все годовые тарифы облачной версии Битрикс24 до 31 июля 2026 года!
Назад

Расширяем bitrix:search.title: добавляем поиск по пользовательским свойствам и торговым предложениям

Расширяем bitrix:search.title: добавляем поиск по пользовательским свойствам и торговым предложениям
Расширяем bitrix:search.title: добавляем поиск по пользовательским свойствам и торговым предложениям

Стандартный компонент bitrix:search.title (строка поиска с выпадающими подсказками) — удобный инструмент, но по умолчанию он ищет только по заголовкам элементов инфоблоков. Этого часто бывает недостаточно, когда ключевая информация хранится в пользовательских свойствах: артикулах, брендах, цветах, странах производителя. А если у вас товар с торговыми предложениями (разные размеры, цвета), то поиск по заголовку основного товара и вовсе теряет многие полезные запросы пользователей.

В этой статье я покажу, как «научить» компонент bitrix:search.title искать:

  • по одному или нескольким пользовательским свойствам элемента;

  • по свойствам типа «Список»;

  • по данным из торговых предложений (SKU).

Всё это реализуется через событие BeforeIndex без единого изменения ядра или стандартных шаблонов.

Как это работает

Перед тем как запись попадает в поисковый индекс, модуль поиска генерирует событие BeforeIndex. Мы можем перехватить его и изменить поле TITLE — именно по нему происходит поиск в компоненте bitrix:search.title. Добавляя в TITLE дополнительные данные (значения свойств, названия предложений, артикулы), мы включаем их в область поиска.

Всё, что требуется — создать обработчик события и один раз перестроить индекс.

Базовый вариант: поиск по одному свойству

Начнём с простого примера. Допустим, у вас есть свойство ARTICLE (артикул), и вы хотите, чтобы товар находили по его значению.

Шаг 1. Добавляем обработчик в init.php

Откройте файл /local/php_interface/init.php (если его нет — создайте) и добавьте код:

<?php
AddEventHandler('search', 'BeforeIndex', 'BeforeIndexHandler');

function BeforeIndexHandler($arFields)
{
    if (!CModule::IncludeModule('iblock')) {
        return $arFields;
    }

    if ($arFields['MODULE_ID'] == 'iblock') {
        $propertyValue = CIBlockElement::GetProperty(
            $arFields['PARAM2'],        // ID инфоблока
            $arFields['ITEM_ID'],       // ID элемента
            ['sort' => 'asc'],
            ['CODE' => 'ARTICLE']       // символьный код свойства
        );

        if ($prop = $propertyValue->Fetch()) {
            $arFields['TITLE'] .= ' ' . $prop['VALUE'];
        }
    }

    return $arFields;
}

Шаг 2. Переиндексация поиска

Зайдите в административную панель:
https://ваш-сайт.ру/bitrix/admin/search_reindex.php?lang=ru

  • Снимите галочку «Переиндексировать только измененные документы».

  • Нажмите «Переиндексировать».

Шаг 3. Проверка

Теперь при вводе артикула в поисковую строку товар будет найден, даже если артикул отсутствует в заголовке.

Расширенный вариант: несколько свойств и торговые предложения

В реальных проектах обычно требуется больше гибкости. Рассмотрим ситуацию:

  • У товара есть свойства «Бренд», «Цвет», «Страна».

  • Товар имеет торговые предложения (SKU) с собственными артикулами и названиями (например, «Кроссовки 41 размер»).

  • Нужно, чтобы поиск находил товар по любому из этих параметров.

Полный код обработчика

<?php
// /local/php_interface/init.php

AddEventHandler('search', 'BeforeIndex', 'BeforeIndexHandler');

function BeforeIndexHandler($arFields)
{
    if (!CModule::IncludeModule('iblock')) {
        return $arFields;
    }

    if ($arFields['MODULE_ID'] !== 'iblock') {
        return $arFields;
    }

    $additionalData = [];

    // ------------------------------------------------------------
    // 1. Несколько свойств самого элемента
    // ------------------------------------------------------------
    $propertyCodes = ['ARTICLE', 'BRAND', 'COLOR', 'COUNTRY']; // укажите свои коды

    $resProps = CIBlockElement::GetProperty(
        $arFields['PARAM2'],
        $arFields['ITEM_ID'],
        'sort' => 'asc',
        ['CODE' => $propertyCodes]
    );

    while ($prop = $resProps->Fetch()) {
        if (empty($prop['VALUE'])) {
            continue;
        }

        // Для свойств типа "Список" берём текст, а не ID
        $value = ($prop['PROPERTY_TYPE'] == 'L') 
            ? $prop['VALUE_ENUM'] 
            : $prop['VALUE'];
        
        $additionalData[] = $value;
    }

    // ------------------------------------------------------------
    // 2. Торговые предложения (SKU)
    // ------------------------------------------------------------
    $offersIblockId = getOffersIblockId($arFields['PARAM2']);

    if ($offersIblockId) {
        $offers = CIBlockElement::GetList(
            [],
            [
                'IBLOCK_ID' => $offersIblockId,
                'PROPERTY_CML2_LINK' => $arFields['ITEM_ID'],
            ],
            false,
            ['nTopCount' => 30], // ограничиваем количество для производительности
            ['ID', 'NAME', 'IBLOCK_ID']
        );

        while ($offer = $offers->Fetch()) {
            // Добавляем название предложения
            $additionalData[] = $offer['NAME'];

            // Добавляем свойства предложения (например, артикул варианта)
            $offerProps = CIBlockElement::GetProperty(
                $offersIblockId,
                $offer['ID'],
                'sort' => 'asc',
                ['CODE' => 'ARTICLE_OFFER'] // свойство для предложений
            );

            while ($offerProp = $offerProps->Fetch()) {
                if (!empty($offerProp['VALUE'])) {
                    $additionalData[] = $offerProp['VALUE'];
                }
            }
        }
    }

    // ------------------------------------------------------------
    // 3. Объединяем всё и добавляем к заголовку
    // ------------------------------------------------------------
    if (!empty($additionalData)) {
        $uniqueData = array_unique($additionalData);
        $arFields['TITLE'] .= ' ' . implode(' ', $uniqueData);
    }

    return $arFields;
}

/**
 * Возвращает ID инфоблока торговых предложений для обычного инфоблока
 */
function getOffersIblockId($catalogIblockId)
{
    if (!\Bitrix\Main\Loader::includeModule('catalog')) {
        return null;
    }

    $catalogInfo = \Bitrix\Catalog\CatalogIblockTable::getList([
        'select' => ['PRODUCT_IBLOCK_ID'],
        'filter' => ['=IBLOCK_ID' => $catalogIblockId],
    ])->fetch();

    return $catalogInfo['PRODUCT_IBLOCK_ID'] ?? null;
}

Что здесь происходит

  1. Несколько свойств — мы передаём массив кодов в CIBlockElement::GetProperty и получаем все значения за один запрос.

  2. Свойства-списки — определяем тип 'L' и используем VALUE_ENUM вместо VALUE.

  3. Торговые предложения — находим инфоблок SKU через CatalogIblockTable, затем для каждого предложения берём его название и дополнительные свойства.

  4. Удаляем дубли — с помощью array_unique избегаем многократного повторения одинаковых слов в индексе.

  5. Ограничение количества предложений — параметр nTopCount защищает от падения производительности, если у товара сотни вариантов.

Пример работы

Представим товар в каталоге:

  • Название товара: «Кроссовки Nike Air Max»

  • Свойства: BRAND = NikeCOLOR = БелыйCOUNTRY = Вьетнам

  • Предложение 1: «Размер 41», артикул NK-AM-41

  • Предложение 2: «Размер 42», артикул NK-AM-42

После индексации поле TITLE будет выглядеть так:

Кроссовки Nike Air Max Nike Белый Вьетнам Размер 41 NK-AM-41 Размер 42 NK-AM-42

Теперь пользователь найдёт этот товар по запросам:

  • Nike

  • Белый

  • Вьетнам

  • 41

  • NK-AM-41

  • 42 размер

Оптимизация для больших каталогов

Если у вас тысячи товаров и у каждого десятки предложений, перебор всех предложений при индексации может стать проблемой. Вот несколько решений:

1. Сократите количество индексируемых предложений

['nTopCount' => 20] // максимум 20 предложений на товар

2. Индексируйте только уникальные ключевые слова

Вместо добавления всех названий предложений, можно добавить только уникальные характеристики:

$sizes = [];
while ($offer = $offers->Fetch()) {
    // Извлекаем размер из названия
    if (preg_match('/размер (\d+)/i', $offer['NAME'], $matches)) {
        $sizes[] = $matches[1];
    }
}
if ($sizes) {
    $additionalData[] = 'размеры: ' . implode(',', array_unique($sizes));
}

3. Используйте GetList для свойств вместо множественных GetProperty

$elem = CIBlockElement::GetList(
    [],
    ['ID' => $arFields['ITEM_ID']],
    false,
    false,
    ['ID', 'PROPERTY_ARTICLE', 'PROPERTY_BRAND', 'PROPERTY_COLOR']
)->Fetch();

$additionalData[] = $elem['PROPERTY_ARTICLE_VALUE'];
$additionalData[] = $elem['PROPERTY_BRAND_VALUE'];
$additionalData[] = $elem['PROPERTY_COLOR_VALUE'];

Этот способ делает один запрос к БД вместо нескольких.

Важные замечания

  1. Переиндексация обязательна после любого изменения кода обработчика. Без неё старые записи в индексе не обновятся.

  2. Не все типы свойств подходят. Свойства типа «Файл», «Дата», «Привязка к пользователям» бессмысленно добавлять в текст. Ограничьтесь строками, списками и числами.

  3. Влияние на размер индекса. Чем больше данных вы добавите в TITLE, тем тяжелее будет индекс. Добавляйте только релевантную для поиска информацию.

  4. Многоязычность. Если сайт многоязычный, свойство может хранить значения на разных языках. Учитывайте $arFields['LID'] при выборке.

  5. Сложные свойства. Для свойств типа «Привязка к элементам» нужно дополнительно получать заголовки связанных элементов через CIBlockElement::GetByID.

Заключение

Мы расширили компонент bitrix:search.title, добавив в него поиск по:

  • одному и нескольким пользовательским свойствам;

  • свойствам-спискам;

  • названиям и свойствам торговых предложений.

Всё это сделано через событие BeforeIndex, без модификации ядерных файлов и стандартных компонентов. Такой подход:

  • безопасен при обновлениях платформы;

  • легко настраивается под конкретные задачи;

  • работает «из коробки» с любым компонентом, использующим поисковый индекс (не только search.title).

Теперь ваш поиск станет действительно полезным для клиентов: они смогут находить товары по артикулам, брендам, цветам, размерам — любой информации, которую вы сочтёте важной.

Не настраиваете поиск — теряете продажи

Внедрим поиск по любым свойствам, торговым предложениям и характеристикам. Клиенты найдут нужный товар за секунды.

Заказать доработку
Читайте по теме
Все статьи
Нужен надежный исполнитель?
Разрабатываем сайты, выполняем миграцию на Битрикс, дорабатываем функционал, сопровождаем проекты, а также занимаемся поисковым продвижением и комплексным маркетингом
Получить консультацию
Все статьи
Содержание