В WordPress часто возникает задача вывести список записей с фильтрацией по нескольким параметрам и при этом корректно реализовать пагинацию. В стандартном WP_Query пагинация работает только с базовыми запросами, а при добавлении пользовательских фильтров могут возникать проблемы. В этой статье подробно разберём, как создать фильтрованные запросы с поддержкой пагинации, используя правильный подход и примеры кода.
Почему стандартная пагинация не работает с пользовательскими фильтрами
Когда вы создаёте свой WP_Query с нестандартными параметрами, например, фильтруете записи по метаданным или таксономиям, пагинация может не работать, так как WordPress не всегда знает, какой URL использовать для следующей страницы. Основная проблема в том, что параметры запроса не передаются в ссылках пагинации, и при переходе на следующую страницу фильтры теряются.
Например, если вы фильтруете записи по кастомному полю и выводите их в шаблоне, то ссылки вида /page/2/ не будут содержать параметры фильтрации, и результат будет уже другим.
Поэтому важно правильно передавать параметры фильтра в URL и корректно формировать WP_Query с учетом текущей страницы.
Как правильно передавать параметры фильтрации в URL
Есть два основных способа передать параметры фильтра:
- Через GET-параметры, например,
?color=red&size=large - Через структуру ЧПУ, например,
/color/red/size/large/page/2/
Первый способ проще реализовать, особенно если вы делаете фильтры через форму с методом GET. Второй требует дополнительной настройки пермалинков и обработки запросов.
В этой статье рассмотрим вариант с GET-параметрами, так как он универсален и проще в поддержке.
Пример реализации фильтра с пагинацией на основе GET-параметров
Допустим, у вас есть посты с метаполями color и size, и вы хотите фильтровать записи по этим параметрам.
Шаг 1. Получаем параметры из URL
function wpbox_get_filtered_posts() {
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$meta_query = array('relation' => 'AND');
if (!empty($_GET['color'])) {
$meta_query[] = array(
'key' => 'color',
'value' => sanitize_text_field($_GET['color']),
'compare' => '='
);
}
if (!empty($_GET['size'])) {
$meta_query[] = array(
'key' => 'size',
'value' => sanitize_text_field($_GET['size']),
'compare' => '='
);
}
$args = array(
'post_type' => 'post',
'posts_per_page' => 10,
'paged' => $paged,
'meta_query' => $meta_query,
);
$query = new WP_Query($args);
return $query;
}Здесь мы формируем массив meta_query в зависимости от переданных параметров, а также учитываем текущую страницу пагинации.
Шаг 2. Вывод записей и пагинации
После получения объекта WP_Query выводим посты и ссылки пагинации, передавая текущие параметры в URL.
function wpbox_render_filtered_posts() {
$query = wpbox_get_filtered_posts();
if ($query->have_posts()) {
echo '<ul>';
while ($query->have_posts()) {
$query->the_post();
echo '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
}
echo '</ul>';
// Формируем базовый URL с параметрами фильтра
$base_url = remove_query_arg('paged');
$base_url = add_query_arg($_GET, $base_url);
// Вывод пагинации
echo paginate_links(array(
'total' => $query->max_num_pages,
'current' => max(1, get_query_var('paged')),
'format' => '&paged=%#%',
'base' => $base_url . '%_%',
'add_args' => false,
));
} else {
echo '<p>Записи не найдены.</p>';
}
wp_reset_postdata();
}Здесь важный момент — мы формируем базовый URL, в который добавляем все текущие GET-параметры, кроме paged, и используем его в пагинации. Это позволяет сохранять фильтры при переходе между страницами.
Реализация формы фильтра
Для удобства пользователям можно создать форму, которая будет отправлять параметры через GET:
<form method="get" action="">
<label>Цвет:</label>
<select name="color">
<option value="">Все</option>
<option value="red">Красный</option>
<option value="blue">Синий</option>
</select>
<label>Размер:</label>
<select name="size">
<option value="">Все</option>
<option value="large">Большой</option>
<option value="small">Маленький</option>
</select>
<input type="submit" value="Фильтровать" />
</form>Чтобы при повторном выводе формы выбранные опции сохранялись, можно добавить PHP-код для установки атрибута selected.
Дополнительные советы по работе с фильтрами и пагинацией
Использование плагинов для удобства
Если вы хотите упростить реализацию фильтров, можно использовать плагины с поддержкой AJAX и пагинации, например:
- ABC Pagination — более гибкая пагинация
- Clearfy Pro — оптимизация и улучшение запросов
Оптимизация запросов
При множественных фильтрах запросы к базе могут стать тяжёлыми. Используйте индексы для метаданных, кеширование запросов и избегайте слишком сложных связок.
Поддержка AJAX-фильтрации
Для лучшего UX можно реализовать фильтрацию и пагинацию без перезагрузки страницы с помощью AJAX. В таком случае важно корректно изменять URL с помощью History API, чтобы сохранялись параметры и можно было делиться ссылками.
Итоги
Создание фильтрованных запросов с поддержкой пагинации — частая задача в разработке на WordPress. Ключевые моменты:
- Передавайте параметры фильтра через GET
- Учитывайте параметр paged в WP_Query
- Формируйте ссылки пагинации с сохранением фильтров
- При необходимости используйте AJAX для улучшения UX
Используя описанный подход и примеры кода, вы сможете создавать удобные и корректные фильтры на сайте, что улучшит опыт пользователей и функциональность ресурса.