Как создать фильтр результатов поиска в WordPress

Нативный поиск в WordPress работает неплохо. Но его возможности можно расширить с помощью системы фильтров. Всё, что вам нужно для этого, немного PHP-кода и небольшое ноу-хау.

Итоговый результат

Итоговый результат

Вот как будет выглядеть итоговый результат.

1. HTML- код

Мы будем использовать тему Twenty Seventeen. Скачайте ее и откройте в редакторе кода. В файле search.php перейдите на строку 26. Под ней добавьте HTML-код меню фильтров.

<h3 class="page-title">
	Filter By
</h3>

<nav class="page-nav">
	<a class="current" href="#">
		All
	</a>
	<a href="#">
		Posts
	</a>
	<a href="#">
		Pages
	</a>
</nav>

Как видите, мы используем стандартный элемент nav с несколькими ссылками внутри него.

Также добавьте заголовок, применив для этого стандартный класс page-title из темы Twenty Seventeen.

2. CSS- код

CSS- код достаточно прост. Тема Twenty Seventeen предоставляет большинство стилей для отступов и шрифтов.

Откройте файл style.css, прокрутите его в самый низ и добавьте следующий CSS-код:

.page-nav {
	margin-bottom: 70px;
	padding-bottom: 70px;
	display: flex;
	flex-wrap: wrap;
	border-bottom: 2px solid #eee;
}

.page-nav a {
	padding: 5px 20px;
	border-radius: 1000px;
	background: #eee;
}

.page-nav a:hover {
	background: #ddd;
}

.page-nav a.current {
	background: #222;
	color: #fff;
}

.page-nav a:not(:last-child) {
	margin-right: 20px;
}

Единственный момент, требующий внимания, это использование .page-nav a:not(:last-child). Это значит: “применить ко всем ссылкам, кроме последней”.

3. PHP- код

Откройте файл functions.php. Добавьте приведенный ниже код в самый низ, чтобы отделить этот код от основного.

Чтобы применять CSS-класс .current к ссылкам элемента nav, нужно создать новую функцию ip_search_filter_item_class();.

Заметьте, что мы используем префикс ip_ в начале имени функции. На сайте могут быть установлены другие плагины, которые используют функцию search_filter_item_class();. Применение префикса существенно снижает вероятность возникновения ошибки.

function ip_search_filter_item_class($passed_string = false) {

}

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

$post_type = (isset($_GET['post_type']) ? $_GET['post_type'] : false);

if($passed_string == $post_type) {
	echo 'current';
}

Перед тем, как создать основную функцию, добавьте следующий код в HTML-файл:

<nav class="page-nav">
<a class="<?php echo (!isset($_GET['post_type']) ? 'current' : false); ?>" href="#">
		All
	</a>
	<a class="<?php ip_search_filter_item_class('post'); ?>" href="#">
		Posts
	</a>
	<a class="<?php ip_search_filter_item_class('page'); ?>" href="#">
		Pages
	</a>
</nav>

Теперь добавим корректные URL- адреса к этим ссылкам:

<nav class="page-nav">
<a class="<?php echo (!isset($_GET['post_type']) ? 'current' : false); ?>" href="<?php echo home_url(); ?>?s=<?php echo get_search_query(); ?>">
		All
	</a>
	<a class="<?php ip_search_filter_item_class('post'); ?>" href="<?php echo home_url(); ?>?s=<?php echo get_search_query(); ?>&post_type=post">
		Posts
	</a>
	<a class="<?php ip_search_filter_item_class('page'); ?>" href="<?php echo home_url(); ?>?s=<?php echo get_search_query(); ?>&post_type=page">
		Pages
	</a>
</nav>

Мы получаем адрес URL-адрес домашней страницы и добавляем к нему параметр ?s= вместе с поисковым запросом. У вас должен получиться примерно такой URL- адрес:

http://localhost:8888/wordpress/?s=test&post_type=page

Ссылка на пост работает, а ссылка на страницу – нет. Исправим это в следующей функции фильтра результатов поиска:

function ip_search_filter($query) {

}

add_filter('pre_get_posts', 'ip_search_filter');

Затем настроим возврат запроса и проверку того, не находимся ли мы в панели администрирования:

function ip_search_filter($query) {
	// Проверяем, что мы не в панели администрирования
	if(!is_admin()) {

	}

	// Возвращаем результат
	return $query;
}

add_filter('pre_get_posts', 'ip_search_filter');

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

// Проверяем, что это главный запрос поиска
if($query->is_main_query() && $query->is_search()) {

}

Последним шагом будет получение значения переменной $_GET['post_type'], его обработка и применение к текущему запросу:

// Проверяем, задана ли $_GET['post_type']
if(isset($_GET['post_type']) && $_GET['post_type'] != '') {
	// Фильтруем его для безопасности
	$post_type = sanitize_text_field($_GET['post_type']);

	// Устанавливаем тип поста
	$query->set('post_type', $post_type);
}

PHP-код создан и размещён в нужном месте.

4. Итоговый код примера

HTML-код

<h3 class="page-title">
	Filter By
</h3>

<nav class="page-nav">
	<a class="<?php echo (!isset($_GET['post_type']) ? 'current' : false); ?>" href="<?php echo home_url(); ?>?s=<?php echo get_search_query(); ?>">
		All
	</a>
	<a class="<?php ip_search_filter_item_class('post'); ?>" href="<?php echo home_url(); ?>?s=<?php echo get_search_query(); ?>&post_type=post">
		Posts
	</a>
	<a class="<?php ip_search_filter_item_class('page'); ?>" href="<?php echo home_url(); ?>?s=<?php echo get_search_query(); ?>&post_type=page">
		Pages
	</a>
</nav>

CSS-код

.page-nav {
	margin-bottom: 70px;
	padding-bottom: 70px;
	display: flex;
	flex-wrap: wrap;
	border-bottom: 2px solid #eee;
}

.page-nav a {
	padding: 5px 20px;
	border-radius: 1000px;
	background: #eee;
}

.page-nav a:hover {
	background: #ddd;
}

.page-nav a.current {
	background: #222;
	color: #fff;
}

.page-nav a:not(:last-child) {
	margin-right: 20px;
}

PHP-код

function ip_search_filter_item_class($passed_string = false) {
	$post_type = (isset($_GET['post_type']) ? $_GET['post_type'] : false);

	if($passed_string == $post_type) {
		echo 'current';
	}
}

function ip_search_filter($query) {
	// Проверяем, что мы не в административной области
	if(!is_admin()) {
		// Проверяем, что это главный запрос поиска
		if($query->is_main_query() && $query->is_search()) {
			// Проверяем, задана ли $_GET['post_type']
			if(isset($_GET['post_type']) && $_GET['post_type'] != '') {
				// Фильтруем его для безопасности
				$post_type = sanitize_text_field($_GET['post_type']);

				// Устанавливаем тип поста
				$query->set('post_type', $post_type);
			}
		}
	}

	// Возвращаем результат
	return $query;
}

add_filter('pre_get_posts', 'ip_search_filter');

Созданный нами поисковый фильтр легко расширяется. На его основе можно создать более мощные системы сортировки поисковых результатов для WordPress-сайта.

 

Сергей Бензенкоавтор-переводчик статьи «How to Make a Search Results Filter in WordPress»