Localizator, simpleSearch или поиск для бедных

У меня возникла проблема с организацией поиска на многоязычных сайтах.
Многоязычные сайты я создаю при помощи компонента Localizator, а для поиска использую компонент simpleSearch, однако данный компонент не умеет из коробки проводить поиск по локализованным ресурсам, поскольку они представляют собой отдельную таблицу в базе данных.
Я нашел некоторое решение этой проблемы, не претендующее ни на что, однако для моих задач вполне подходящее.
Делюсь с вами, возможно кому-то принесет пользу.
Итак к делу.
Нам нужны
— localizator
— simpleSearch
— вещи типа pdoTools считаю, что у вас установлены по умолчанию.
Первое.
Читаем инструкцию по работе simpleSearch и видим, что компонент научился искать по другим таблицам (видимо его недавно доработали, потому как раньше я не находил такой информации)
docs.modx.com/extras/revo/simplesearch/simplesearch.simplesearch#SimpleSearch.SimpleSearch-SearchingCustomTables
А значит нам нужно вызвать сниппет поиска передав ему параметры, которые помогут искать в таблицах локализатора.
{var $finds = '!mySearch'|snippet:
['customPackages'=>'localizatorContent:pagetitle,content:localizator:{core_path}components/localizator/model/:localizatorContent.resource_id = modResource.id']
}
Вызываем его на той страницу, на которой планируем показывать результаты и результат его работы сразу запишем в переменную.
Второе. Мы видим, что вызывается сниппет mySearch — это измененная копия стандартного сниппета simpleSearch. Зачем он нужен, ведь мы уже настроили поиск по таблице локализатора и таки да, это работает. Но, сниппет simpleSearch хоть и найдет товары или ресурсы по их английскому (или другому) названию, но результаты вам выдаст только на русском языке. Поиск происходить будет, товар (в моем случае часы), могут быть найдены как watch но результаты поиска будут на русском языке.
Как это исправить? Сделаем копию сниппета и доработаем его для наших нужд. Вот его код.
<?php
/**
 * SimpleSearch snippet modified to work with Localizator
 *
 * @var modX $modx
 * @var array $scriptProperties
 * @package simplesearch
 */
require_once $modx->getOption(
        'simplesearch.core_path',
        null,
        $modx->getOption('core_path') . 'components/simplesearch/'
    ) . 'model/simplesearch/simplesearch.class.php';
$search = new SimpleSearch($modx, $scriptProperties);

/* Find search index and toplaceholder setting */
$searchIndex   = $modx->getOption('searchIndex', $scriptProperties, 'search');
$toPlaceholder = $modx->getOption('toPlaceholder', $scriptProperties, false);
$noResultsTpl  = $modx->getOption('noResultsTpl', $scriptProperties, 'SearchNoResults');

/* Get search string */
if (empty($_REQUEST[$searchIndex])) {
   return false;
}
$searchString = $search->parseSearchString($_REQUEST[$searchIndex]);
if (!$searchString) {
    

    return false;
}

/* Setup default properties. */
$tpl               = $modx->getOption('tpl', $scriptProperties, 'SearchResult');
$containerTpl      = $modx->getOption('containerTpl', $scriptProperties, 'SearchResults');
$showExtract       = $modx->getOption('showExtract', $scriptProperties, true);
$extractSource     = $modx->getOption('extractSource', $scriptProperties, 'content');
$extractLength     = $modx->getOption('extractLength', $scriptProperties, 200);
$extractEllipsis   = $modx->getOption('extractEllipsis', $scriptProperties, '...');
$highlightResults  = $modx->getOption('highlightResults', $scriptProperties, true);
$highlightClass    = $modx->getOption('highlightClass', $scriptProperties, 'simplesearch-highlight');
$highlightTag      = $modx->getOption('highlightTag', $scriptProperties, 'span');
$perPage           = $modx->getOption('perPage', $scriptProperties, 10);
$pagingSeparator   = $modx->getOption('pagingSeparator', $scriptProperties, ' | ');
$placeholderPrefix = $modx->getOption('placeholderPrefix', $scriptProperties, 'simplesearch.');
$includeTVs        = $modx->getOption('includeTVs', $scriptProperties, '');
$processTVs        = $modx->getOption('processTVs', $scriptProperties, '');
$tvPrefix          = $modx->getOption('tvPrefix', $scriptProperties, '');
$offsetIndex       = $modx->getOption('offsetIndex', $scriptProperties, 'simplesearch_offset');
$idx               = isset($_REQUEST[$offsetIndex]) ? (int) $_REQUEST[$offsetIndex] + 1 : 1;
$postHooks         = $modx->getOption('postHooks', $scriptProperties, '');
$activeFacet       = $modx->getOption('facet',$_REQUEST,$modx->getOption('activeFacet', $scriptProperties, 'default'));
$activeFacet       = $modx->sanitizeString($activeFacet);
$facetLimit        = $modx->getOption('facetLimit', $scriptProperties, 5);
$outputSeparator   = $modx->getOption('outputSeparator', $scriptProperties, "\n");
$addSearchToLink   = (int) $modx->getOption('addSearchToLink', $scriptProperties, 0);
$searchInLinkName  = $modx->getOption('searchInLinkName', $scriptProperties, 'search');

/* Get results */
$response     = $search->getSearchResults($searchString, $scriptProperties);
$placeholders = array('query' => $searchString);
$resultsTpl   = array('default' => array('results' => array(), 'total' => $response['total']));
if (!empty($response['results'])) {
    /* iterate through search results */
    $searcResults='';
   
    foreach ($response['results'] as $resourceArray) {
        $searcResults.=$resourceArray['id'].',';
    }
    return $searcResults;
}
Пара слов для пояснения. Сниппет переписан так, чтобы если ничего не найдено вернуть false, а если есть результат или результаты, то просто вернуть строку с идентификаторами найденных ресурсов, перечисленных через запятую.
Три. На страницу показа результатов нужно как-то попасть. Это будет get запрос из формы поиска. По умолчанию, simpleSearch для вывода формы использует отдельный сниппет simpleSearchForm, но с ним возникает проблема. Наша форма должна понимать, какой язык сейчас включен на сайте и посылать нас не просто на страницу результатов, а на разные версии этой страницы. Поэтому я рекомендую использовать просто форму.
<form action="{'cultureKey'|option}/{25|url}" class="search-form sisea-search-form" method="get">
                            <input type="hidden" name="id" value="25" />
                            <input type="search"  name="search" id="search" value="{$.get.search}" >
                            <button type="submit"><i class="fas fa-search"></i></button>
                        </form>
Ее отличие в том, что она подставит перед url страницы (в моем случае страница поиска имеет идентификатор 25) еще и значение системной настройки cultureKey и если поиск ведется на англ версии сайта, то и перейдем мы на англ страницу поиска.
Четыре. На страницу поиска мы попали. В наше переменную $finds попадет либо false либо строка с идентификаторами ресурсов. И в этом то и прелесть. Имея этот список идентификаторов, мы уже не зависимы от языка. Достаточно далее в странице вызвать такой код
{if $finds?}
                            {'!msProducts' | snippet : [
                            'parents'=>3,
                            'resources'=>$finds,
                            'tvPrefix'=>'',
                            'limit'=>0,
                            'tpl'=>'productInRow.tpl',
                            'leftJoin' => '{
                                "localizator" : {
                                "class" : "localizatorContent",
                                "alias" : "localizator",
                                "on" : "localizator.resource_id = msProduct.id"
                                }
                            }',
                        'select' => '{ "localizator" : "msProduct.*, localizator.*, msProduct.id" }',
                        'where' => '{ "localizator.key" : "' ~ ('localizator_key' | option) ~ '"}'
                        ]}

                        {else}
                           {'noresults'|lexicon}
                        {/if}
и мы будем получать результаты на нужном нам языке. Если в переменной что-то находится, то вызовем сниппет (в моем случае msProducts но может быть и pdoResources) передаем ему строку из переменной finds и видим найденные ресурсы на нужном языке. {'noresults'|lexicon} — это просто фраза, о том что ничего не найдена, заведенная через лексиконы.
Как-то так.
Александр Мельник
23 февраля 2019, 17:07
7
455
+7

Комментарии: 0

Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.