WordPress: Поиск по Сайту (без плагинов)

Сегодня разберёмся, как в WordPress реализовать AJAX поиск по сайту (так называемый «Живой поиск») без использования плагинов. Настроим его должным образом. Рассмотрим, как реализовать поиск по записям, страницам или произвольным типам записей. А также исключим определённые страницы/записи из поиска.

Содержание:

  1. код поиска WordPress (HTML, CSS);
  2. AJAX поиск (JavaScript);
  3. настройка поиска (functions.php);
    1. поиск по записям;
    2. поиск по страницам;
    3. поиск по произвольным типам записей;
  4. включения нужных типов записей в поиск;
    1. включение только записей в поиск
    2. включение произвольного типа записей
    3. включение нескольких типов записей в поиск
  5. исключение страниц/произвольных записей из поиска;
    1. исключение страниц по id;
    2. исключение кастомных типов записей;
    3. исключение категорий по id;
  6. подсветка результатов поиска;
  7. admin-ajax.php bad request 400.

Код поиска WordPress

Код поиска находится в файле searchform.php. Именно данный файл вам нужно выводить в том месте, где это необходимо. Чтобы вывести форму поиска WordPress, воспользуйтесь следующим кодом.

<?php get_search_form(); ?>

Ваш шаблон поиска searchform.php может выглядеть примерно так.

<form
    class="search-form"
    role="search"
    method="get"
    id="searchform"
    action="<?php echo home_url('/') ?>"
>
    <input
        class="search-form__input"
        type="text"
        value="<?php echo get_search_query() ?>"
        name="s" id="s"
        placeholder="Поиск на сайте WordPress"
        autocomplete="off"
    />
    <button type="submit" id="searchsubmit">
        <svg xmlns="http://www.w3.org/2000/svg" width="19.856" height="20.848" viewBox="0 0 19.856 20.848">
            <path d="M91.119,310.567l-4.713-4.713a8.8,8.8,0,0,0,2.51-6.147,8.708,8.708,0,1,0-8.708,8.708,8.983,8.983,0,0,0,5.02-1.588l4.815,4.815a.877.877,0,0,0,1.127,0A.792.792,0,0,0,91.119,310.567ZM73.037,299.708a7.171,7.171,0,1,1,7.171,7.171A7.192,7.192,0,0,1,73.037,299.708Z" transform="translate(-71.5 -291)" fill="#414544" />
        </svg>
    </button>
    <ul class="ajax-search"></ul>
</form>

Стили для выпадающего списка результатов поиска.

/* ajax search */

.search-form {
    position: relative;
}

.ajax-search {
    position: absolute;
    top: 100%;
    left: 0;
    width: 100%;
    right: 0;
    background: #fff;
    box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
    border-radius: 10px;
    margin-top: 5px;
    max-height: 230px;
    overflow-x: hidden;
    overflow-y: auto;
    z-index: 100;
    margin: 0;
    padding: 0;
    font-size: 14px;
    color: #424348;
    scrollbar-color: dark;
    scrollbar-width: thin;
    overscroll-behavior: contain;
}

.ajax-search::-webkit-scrollbar {
    width: 6px;
    background-color: #eff2f3;
}

.ajax-search::-webkit-scrollbar-thumb {
    background-color: #dddddd;
    border-radius: 4em;
}

.ajax-search__item {
    position: relative;
    border-top: 1px solid rgba(224, 229, 231, 0.5);
    padding: 10px 15px;
    cursor: pointer;
    list-style-type: none;
}

.ajax-search__link {
    color: var(--accent);
    line-height: 130%;
    margin-bottom: 10px;
    font-size: 13px;
    display: block;
}

.ajax-search__excerpt {
    cursor: default;
    font-size: 11px;
    line-height: 140%;
}

.ajax-search__not-found {
    font-size: 12px;
}

Живой поиск в WordPress

Для реализации живого поиска мы будем использовать технологию AJAX. Таким образом, поиск по сайту WordPress будет осуществляться без перезагрузки страницы.

При вводе текста мы будем отправлять AJAX запрос в php-обработчик (создадим его в следующем пункте данной статьи). При нахождении или не нахождении данных мы будем выводить пользователю результаты поиска в виде списка <ul class="ajax-search"></ul>, который мы подготовили в предыдущем пункте статьи.

Создайте файл ajax-search.js или просто добавьте следующий JavaScript код в ваш главный javascript файл.

jQuery(document).ready(function ($) {
    const search_input = $('.search-form__input');
    const search_results = $('.ajax-search');

    search_input.keyup(function () {
        let search_value = $(this).val();

        if (search_value.length > 2) { // кол-во символов

            $.ajax({
                url: '/wp-admin/admin-ajax.php',
                type: 'POST',
                data: {
                    'action': 'ajax_search', // functions.php

                    'term': search_value
                },
                success: function (results) {
                    search_results.fadeIn(200).html(results);
                }
            });
        } else {
            search_results.fadeOut(200);
        }
    });

    // Закрытие поиска при клике вне его

    $(document).mouseup(function (e) {
        if (
            (search_input.has(e.target).length === 0) &&
            (search_results.has(e.target).length === 0)
        ) {
            search_results.fadeOut(200);
        };
    });
});

Если javascript файл вы создали отдельно, не забудьте подключить его в functions.php .

wp_enqueue_script(
    '{название_темы}-ajax-search',
    get_theme_file_uri('assets/js/ajax-search.js'), array(), '', true
);

Настройка поиска WordPress

При вводе в поле поиска отправляется AJAX запрос в функцию ajax_search. Создадим её в functions.php или в отдельном файле, как вам удобно. Я создам отдельно.

Создаю файл /functions/ajax-search.php и подключаю его в functions.php.

require get_template_directory() . '/functions/ajax-search.php'; # AJAX search

Сам код для этого файла.

<?php

// ajax поиск по сайту

add_action('wp_ajax_nopriv_ajax_search', 'ajax_search');
add_action('wp_ajax_ajax_search', 'ajax_search');
function ajax_search()
{
    $args = array(
        'post_type'      => 'any', // Тип записи: post, page, кастомный тип записи

        'post_status'    => 'publish',
        'order'          => 'DESC',
        'orderby'        => 'date',
        's'              => $_POST['term'],
        'posts_per_page' => -1
    );
    $query = new WP_Query($args);
    if ($query->have_posts()) {
        while ($query->have_posts()) {
            $query->the_post(); ?>
            <li class="ajax-search__item">
                <a href="<?php the_permalink(); ?>" class="ajax-search__link"><?php the_title(); ?></a>
                <div class="ajax-search__excerpt"><?php the_excerpt(); ?></div>
            </li>
        <?php }
    } else { ?>
        <li class="ajax-search__item">
            <div class="ajax-search__not-found">Ничего не найдено</div>
        </li>
<?php }
    exit;
}

Обратите внимание на ключ post_type в массиве $args. В данном примере мы осуществляем поиск по всему сайту, т.к. мы использовали значение any. Рассмотрим и другие примеры поиска.

WordPress поиск по записям

Чтобы выполнить поиск только по записям, измените значение any на post.

'post_type' => 'post', // тип записи «Записи»

Поиск по страницам:

'post_type' => 'page', // тип записи «Страницы»

Поиск по кастомным типам записей

Например, мы хотим выполнять поиск по страницам и по произвольному типу записей production, тогда используйте массив для множественного выбора.

'post_type' => array('page', 'production'), // типы записей: «Страницы», «Продукция»

Включение типов записей в поиск

Обратите внимание, все следующие ниже фильтры ниже будут работать на странице поиска, для живого (AJAX) поиска, добавляйте нужные аргументы в свою функцию ajax_search (3 пункт данного руководства). Примеры:

'post_type' => array('page', 'production'), # включение: «Страницы», «Продукция»


'post__in' => array(6, 11, 19), # включение страниц с id 6, 11, 19


'post__not_in' => array(36, 38), # исключение страниц с id 36, 38


'category__not_in' => array(6, 7), # исключение категорий с id 6, 7

Включение записей в поиск

Чтобы включить в поиск только записи, используйте код:

add_filter('pre_get_posts', 'include_search_filter');
function include_search_filter($query)
{
    if (!is_admin() && $query->is_main_query() && $query->is_search) {
        $query->set('post_type', 'post');
    }
    return $query;
}

Включение произвольного типа записей

Чтобы включить в поиск только произвольный тип записи production, используйте следующий код:

add_filter('pre_get_posts', 'include_search_filter');
function include_search_filter($query)
{
    if (!is_admin() && $query->is_main_query() && $query->is_search) {
        $query->set('post_type', 'production');
    }
    return $query;
}

Включение нескольких типов записей в поиск

Чтобы включить сразу несколько типов записей, используйте массив:

add_filter('pre_get_posts', 'include_search_filter');
function include_search_filter($query)
{
    if (!is_admin() && $query->is_main_query() && $query->is_search) {
        $query->set('post_type', array('production', 'page'));
    }
    return $query;
}

Таким образом, мы включили в поиск только «Страницы» и произвольный тип записи «Продукция».

Исключение страниц из поиска WordPress

Иногда может понадобиться исключить определённые страницы из поиска, рассмотрим, как это можно реализовать.

Исключение страниц из поиска по id

Чтобы исключить страницы с определёнными id, воспользуйтесь следующим кодом:

add_action('pre_get_posts', 'my_exclude_search_filter');
function my_exclude_search_filter($query) {
    if (!$query->is_admin && $query->is_search && $query->is_main_query() ) {
        $query->set('post__not_in', array(36, 38) );
    }
}

Так мы исключим из поиска страницы с id 36 и 38.

Исключение произвольных типов записей из поиска

Чтобы исключить кастомный тип записи из поиска, используйте код:

add_action('init', 'exclude_post_type_from_search', 99);
function exclude_post_type_from_search() {
    global $wp_post_types;

    if (post_type_exists('photo_gallery') ) {
        $wp_post_types['photo_gallery']->exclude_from_search = true;
    }
}

Таким образом мы исключили тип записи photo_gallery из поиска.

Исключение категорий из поиска по id

Чтобы исключить определённые категории из поиска, воспользуйтесь кодом ниже.

add_filter('pre_get_posts','my_exclude_category_search_filter');
function my_exclude_category_search_filter($query) {
    if ($query->is_search) {
        $query->set('category__not_in', array(6, 7));
    }
    return $query;
}

Указав в массиве id 6 и 7, мы исключаем из поиска категории с этими id.

Подсветка результатов поиска

При переходе на страницу с результатами поиска, заголовок статьи и the_excerpt/the_content (отрывок или контент) будут подсвечены.

# Подсветка результатов поиска

add_filter('the_content', 'search_results_hightlight');
add_filter('the_excerpt', 'search_results_hightlight');
add_filter('the_title', 'search_results_hightlight');
function search_results_hightlight($text)
{
    // цвета

    $styles = [
        '',
        'color: #000; background: #98fd65;',
        'color: #000; background: #ffcc56;',
        'color: #000; background: #98cefa;',
        'color: #000; background: #fd9897;',
        'color: #000; background: #df7dca;',
    ];

    // только для страницы поиска

    if (!is_search())
        return $text;

    $query_terms = get_query_var('search_terms');

    if (empty($query_terms))
        $query_terms = array_filter([get_query_var('s')]);

    if (empty($query_terms))
        return $text;

    $n = 0;
    foreach ($query_terms as $term) {
        $n++;

        $term = preg_quote($term, '/');
        $text = preg_replace_callback("/$term/iu", function ($match) use ($styles, $n) {
            return '<span style="' . $styles[$n] . '">' . $match[0] . '</span>';
        }, $text);
    }

    return $text;
}

Admin-ajax.php Bad Request 400

Если при вводе в поле поиска в консоли появляется ошибка 400 Bad Request, то ищите проблему в 3 пункте данного руководства. Вероятно, вы неправильно именовали экшены или создали отдельный файл и забыли подключить его (или неправильно подключили).

Думаю, логика использования AJAX поиска на сайте WordPress вам ясна. Если же что-то осталось не понятным, задавайте вопросы в комментариях.

Понравилась статья? - Можете поддержать проект в блоке ниже.

admin