Бывает ситуация, когда нужно настроить страницу поиска для сложного сайта.
Допустим, страница имеет такой вот сложный вид:
kyiv-west.lexus.ua/models/is/features/engine-v6/
Задача: когда мы вводим на странице поиска запрос (кусок текста со страницы какой-нибудь "Особенности") то нам должны вывестись результаты поиска со ссылкой именно на эту страницу.
Пример запроса:
На сайте используется ЧПУ. Поскольку у нас есть физически всего-лишь папка /models/ в которой лежит комплексный компонент. Далее компонент анализирует адресную стркоу, и понимает, что нужно показать страницу "Lexus is" -> "Особенности" -> "Двигатель V6".
Инфоблоки настроены таким образом, что есть один инфоблок "Автомобили", и есть инфоблок "Особенности". Элементы-особенности привязаны к автомобилям.
[spoiler]
Что мы имеем: Для того чтобы это осуществить нужно в свойствах инфоблока "Особенности" задать URL страницы детального просмотра, например, такой:
Поле #EXTERNAL_ID# должно замениться на символьный код автомобиля из инфоблока "Автомобили", а поле #CODE# должно замениться на символьный код особенности из инфоблока "Особенности".
Примечание: Написать здесь свой макрос, например #CAR_CODE#, к сожалению нельзя. Нужно использовать один из стандартных макросов.
Автозамена поля #CODE# и так будет, по умолчанию, а вот чтобы заменить #EXTERNAL_ID# на символьный код автомобиля нужно добавить в init.php обработчик:
Событие BeforeIndex наступает перед индексацией элемента (например, когда мы нажимаем "Сохранить").
Тут я анализирую какой это инфоблок, и если мы сохраняем особенность, то тогда я нахожу символьный код автомобиля для этой особенности, и сохраняю его в переменной EXTERNAL_ID.
Таким образом, элемент проиндексируется, и результат индексации сохранится в таблице b_search_content. В поле SEARCHABLE_CONTENT будет храниться проиндексированный текст, а в поле URL будет храниться набор параметров для формирования ссылки. Например, он может выглядеть так:
Теперь, когда мы на странице поиска нажимаем "Искать" то из этой таблицы ищутся вхождения, и если они найдены - то формируется URL по правилу формирования URL, заданному в настройках инфоблока, к которому принадлежит эта запись.
Дополнительно:
Допустим у нас многоязыковой сайт, в котором перевод на другие языки хранится в дополнительном свойстве. Для того чтобы этот поиск работал нужно поставить в настройках этих свойств галочку "индексировать свойство модулем поиска", и создать событие для добавления в ссылку идентификатора текущего языка:
файл init.php
Тут у меня константа CURRLANG или пустая (если текущий язык - язык по умолчанию), либо имеет вид /ru, /ua, /en и тд.
Известные проблемы (особенности):
Для ЧПУ ссылок нельзя сформировать путь для навигационной цепочки в шаблоне результатов поиска. Так как этот путь формируется фукнцией
а эта фукнция анализирует только содержимое файлов .section.php (настроек раздела). А поскольку у нас все ссылки формируются как ЧПУ на лету, то для них файлов .section.php не существует.
Для нескольких языковых версий если языки похожи (русский и украинский) то в результатах поиска по слову может появляться как укр. так и русский текст (так как мы храним перевод в свойствах одного и того-же элемента, и весь этот текст попадает в SEARCHABLE_CONTENT). Если языки различаются (например, если делать поиск английского слова) то тогда таких проблем не возникает.
Допустим, страница имеет такой вот сложный вид:
kyiv-west.lexus.ua/models/is/features/engine-v6/
Задача: когда мы вводим на странице поиска запрос (кусок текста со страницы какой-нибудь "Особенности") то нам должны вывестись результаты поиска со ссылкой именно на эту страницу.
Пример запроса:
На сайте используется ЧПУ. Поскольку у нас есть физически всего-лишь папка /models/ в которой лежит комплексный компонент. Далее компонент анализирует адресную стркоу, и понимает, что нужно показать страницу "Lexus is" -> "Особенности" -> "Двигатель V6".
Инфоблоки настроены таким образом, что есть один инфоблок "Автомобили", и есть инфоблок "Особенности". Элементы-особенности привязаны к автомобилям.
[spoiler]
Что мы имеем: Для того чтобы это осуществить нужно в свойствах инфоблока "Особенности" задать URL страницы детального просмотра, например, такой:
#SITE_DIR#/models/#EXTERNAL_ID#/features/#CODE#/ |
Поле #EXTERNAL_ID# должно замениться на символьный код автомобиля из инфоблока "Автомобили", а поле #CODE# должно замениться на символьный код особенности из инфоблока "Особенности".
Примечание: Написать здесь свой макрос, например #CAR_CODE#, к сожалению нельзя. Нужно использовать один из стандартных макросов.
Автозамена поля #CODE# и так будет, по умолчанию, а вот чтобы заменить #EXTERNAL_ID# на символьный код автомобиля нужно добавить в init.php обработчик:
// Исправляем ссылки ЧПУ для поиска
AddEventHandler("search", "BeforeIndex", Array("LXVidiSearch", "BeforeIndex"));
class LXVidiSearch
{
function BeforeIndex ($arFields)
{
if ($arFields["MODULE_ID"] == "iblock" && $arFields["PARAM2"] == 262) // Особенности Lexus
{
// Находим автомобиль, которому принадлежит данная особенность
$arFilter = array(
"ID" => $arFields["ITEM_ID"],
"IBLOCK_ID" => $arFields["PARAM2"], // Инфоблок особенностей
);
$arSelect = array(
"ID",
"PROPERTY_CAR_ID",
);
$db_feature = CIblockElement::GetList(array(), $arFilter, false, false, $arSelect);
if ($arFeature = $db_feature->GetNext())
{
// Ищем символьный код автомобиля
$car_id = $arFeature["PROPERTY_CAR_ID_VALUE"];
$arFilter = array(
"ID" => $car_id,
);
$arSelect = array(
"CODE",
);
$db_car = CIblockElement::GetList(array(), $arFilter, false, false, $arSelect);
if ($arCar = $db_car->GetNext())
{
$car_code = $arCar["CODE"];
$arFields["URL"] .= "&EXTERNAL_ID=".$car_code; // Запоминаем символьный код в переменной EXTERNAL_ID
}
}
}
return $arFields;
}
}
|
Событие BeforeIndex наступает перед индексацией элемента (например, когда мы нажимаем "Сохранить").
Тут я анализирую какой это инфоблок, и если мы сохраняем особенность, то тогда я нахожу символьный код автомобиля для этой особенности, и сохраняю его в переменной EXTERNAL_ID.
Таким образом, элемент проиндексируется, и результат индексации сохранится в таблице b_search_content. В поле SEARCHABLE_CONTENT будет храниться проиндексированный текст, а в поле URL будет храниться набор параметров для формирования ссылки. Например, он может выглядеть так:
=ID=12605&EXTERNAL_ID=12605&IBLOCK_SECTION_ID=1138&IBLOCK_TYPE_ID=lexus&IBLOCK_ID=262&IBLOCK_CODE=&IBLOCK_EXTERNAL_ID=&CODE=engine-v6&EXTERNAL_ID=is |
Теперь, когда мы на странице поиска нажимаем "Искать" то из этой таблицы ищутся вхождения, и если они найдены - то формируется URL по правилу формирования URL, заданному в настройках инфоблока, к которому принадлежит эта запись.
Дополнительно:
Допустим у нас многоязыковой сайт, в котором перевод на другие языки хранится в дополнительном свойстве. Для того чтобы этот поиск работал нужно поставить в настройках этих свойств галочку "индексировать свойство модулем поиска", и создать событие для добавления в ссылку идентификатора текущего языка:
файл init.php
AddEventHandler("search", "OnSearchGetURL", array("LXVidiSearchResult", "OnSearchGetURL"));
class LXVidiSearchResult
{
function OnSearchGetURL($arFields)
{
// если это "особенность"
if ($arFields["PARAM2"] == 262)
{
$arFields["URL"] = CURRLANG.$arFields["URL"];
}
return $arFields["URL"];
}
}
|
Тут у меня константа CURRLANG или пустая (если текущий язык - язык по умолчанию), либо имеет вид /ru, /ua, /en и тд.
Известные проблемы (особенности):
Для ЧПУ ссылок нельзя сформировать путь для навигационной цепочки в шаблоне результатов поиска. Так как этот путь формируется фукнцией
$APPLICATION->GetNavChain($ar["URL"]); |
а эта фукнция анализирует только содержимое файлов .section.php (настроек раздела). А поскольку у нас все ссылки формируются как ЧПУ на лету, то для них файлов .section.php не существует.
Для нескольких языковых версий если языки похожи (русский и украинский) то в результатах поиска по слову может появляться как укр. так и русский текст (так как мы храним перевод в свойствах одного и того-же элемента, и весь этот текст попадает в SEARCHABLE_CONTENT). Если языки различаются (например, если делать поиск английского слова) то тогда таких проблем не возникает.