
mSearch
Сниппет для поиска и вывода результатов.
Использует pdoTools для вывода, поэтому поддерживает все основные возможности: подключение TV, указание условий в &where и т.д.
Некэшируемый вызов
Сниппет должен вызываться некэшированно (с !), так как реагирует на поисковый запрос из $_REQUEST.
Параметры
| Параметр | По умолчанию | Описание |
|---|---|---|
| query | $_REQUEST[queryVar] | Поисковый запрос. Если не задан явно — берётся из HTTP-параметра, имя которого указано в queryVar |
| queryVar | mse_query | Имя HTTP-параметра, из которого читается поисковый запрос. Валидируется по regex ^[a-zA-Z_][a-zA-Z0-9_]*$, при невалидном имени — fallback на mse_query |
| tpl | mSearch.row | Чанк оформления для каждого результата |
| tplWrapper | Чанк-обёртка для всех результатов | |
| limit | 10 | Лимит результатов. 0 — без ограничения (полезно для return=ids) |
| toPlaceholder | Сохранить результаты в плейсхолдер вместо вывода | |
| contexts | текущий контекст | Контексты для фильтрации, через запятую (например web,ru). Пустая строка — поиск по всем контекстам |
| return | chunks | Формат вывода: chunks, ids, json, data |
Параметр return
| Значение | Описание |
|---|---|
chunks | Вывод через чанки (по умолчанию) |
ids | Только ID найденных ресурсов через запятую |
json | JSON-массив с данными ресурсов |
data | Массив данных (для использования в других сниппетах) |
Плейсхолдеры
Глобальные плейсхолдеры
После выполнения сниппет устанавливает:
| Плейсхолдер | Описание |
|---|---|
[[+mse.total]] | Общее количество найденных результатов |
[[+mse.query]] | Поисковый запрос |
Плейсхолдеры в чанке tpl
| Плейсхолдер | Описание |
|---|---|
[[+id]] | ID ресурса |
[[+pagetitle]] | Заголовок |
[[+longtitle]] | Расширенный заголовок |
[[+introtext]] | Вводный текст |
[[+weight]] | Релевантность (вес) результата |
[[+intro]] | Фрагмент introtext с подсвеченными совпадениями (HTML-safe) |
[[+idx]] | Порядковый номер в списке |
| и другие поля ресурса... | Доступны все поля, которые загрузил pdoFetch |
Поле content
По умолчанию pdoFetch не загружает поле content (тяжёлое). Чтобы получить [[+content]] в чанке, передайте &includeContent=1`` в вызов сниппета.
Плейсхолдеры в чанке tplWrapper
| Плейсхолдер | Описание |
|---|---|
[[+output]] | Все результаты, склеенные подряд |
[[+total]] | Количество результатов |
[[+query]] | Поисковый запрос |
Примеры
Базовый вызов
{'!mSearch' | snippet}С кастомным чанком
{'!mSearch' | snippet : [
'tpl' => 'mySearchResult',
'limit' => 20
]}С обёрткой
{'!mSearch' | snippet : [
'tpl' => 'mSearch.row',
'tplWrapper' => 'mSearch.wrapper',
'limit' => 10
]}Чанк mSearch.wrapper:
{if $total > 0}
<div class="search-results">
<p>Найдено результатов: {$total} по запросу "{$query}"</p>
<div class="results-list">
{$output}
</div>
</div>
{else}
<p>Ничего не найдено</p>
{/if}С пагинацией через pdoPage
{'!pdoPage' | snippet : [
'element' => 'mSearch',
'tpl' => 'mSearch.row',
'limit' => 10
]}
{$_modx->getPlaceholder('page.nav')}Пагинация
Собственный параметр &offset у mSearch не предусмотрен — пагинация реализуется через обёртку pdoPage, которая управляет порциями результатов и формирует навигацию.
Получение только ID
Полезно для передачи в другие сниппеты:
{set $ids = '!mSearch' | snippet : [
'return' => 'ids',
'limit' => 0
]}
{if $ids}
{'msProducts' | snippet : [
'resources' => $ids,
'sortby' => 'ids'
]}
{else}
<p>Товары не найдены</p>
{/if}Поиск товаров MiniShop3
{'!pdoPage' | snippet : [
'element' => 'msProducts',
'parents' => 0,
'resources' => '!mSearch' | snippet : ['return' => 'ids', 'limit' => 0] | default : '999999',
'sortby' => 'ids',
'tpl' => 'tpl.msProducts.row'
]}
{$_modx->getPlaceholder('page.nav')}Фильтр default
Фильтр | default : '999999' подставляет несуществующий ID, если поиск не дал результатов. Это предотвращает вывод всех товаров при пустом запросе.
JSON для AJAX
{'!mSearch' | snippet : [
'return' => 'json',
'limit' => 5
]}Кастомное имя HTTP-параметра запроса
Используется при миграции с другой платформы, где уже сформированы внешние ссылки с конкретным именем параметра, либо когда на странице несколько форм поиска с разной семантикой:
{'!mSearch' | snippet : ['queryVar' => 'q']}Сниппет прочитает запрос из $_REQUEST['q'] вместо $_REQUEST['mse_query'].
Чанк по умолчанию
Чанк mSearch.row:
<div class="search-result">
<h3>
<a href="{$id | url}">{$pagetitle}</a>
<span class="weight">{$weight}</span>
</h3>
{if $intro}
<p class="intro">{$intro}</p>
{/if}
</div>Подсветка результатов
Плейсхолдер [[+intro]] — фрагмент introtext (длиной по умолчанию 200 символов вокруг первого совпадения) с подсвеченными словами в <mark>.
Highlighter экранирует исходный текст через htmlspecialchars до вставки <mark> — результат HTML-safe, можно безопасно выводить в чанке без дополнительного |escape.
Фильтрация по контексту
По умолчанию сниппет фильтрует результаты по текущему контексту MODX. Это важно для мультиконтекстных сайтов (например, мультиязычных), чтобы пользователи русского сайта не видели в результатах страницы с английского.
{* Поиск только в текущем контексте (по умолчанию) *}
{'!mSearch' | snippet}
{* Поиск в нескольких контекстах *}
{'!mSearch' | snippet : ['contexts' => 'web,ru']}
{* Поиск по всем контекстам *}
{'!mSearch' | snippet : ['contexts' => '']}Алгоритм поиска
- Разбиение запроса — запрос разбивается на слова
- Обработка алиасов — применяются синонимы и замены
- Морфологический анализ — для каждого слова ищутся базовые формы
- Поиск в индексе — поиск слов в таблице индекса с фильтрацией по контексту
- LIKE-поиск — дополнительный поиск по полному тексту (
mse_intro) - Применение бонусов — добавление веса за точные совпадения и за вхождение всех слов
- Сортировка — результаты сортируются по релевантности
События
При поиске вызываются события Searcher:
- mseOnBeforeSearch — перед поиском, можно модифицировать запрос и опции
- mseOnAfterSearch — после поиска, можно модифицировать результаты
События вызываются в Searcher::search(), поэтому срабатывают одинаково и при использовании сниппета, и при прямом обращении к $msearch->search() (например, из своего PHP-кода).
