В WordPress часто возникает задача вывести список записей, отфильтрованных по сложным условиям, включая meta-записи, таксономии и произвольные параметры. При этом важно корректно реализовать пагинацию, чтобы пользователи могли удобно переходить между страницами результатов.
Почему стандартная пагинация не всегда работает с meta-записями
Стандартный класс WP_Query позволяет фильтровать записи с помощью параметра meta_query. Но если запрос сложный и использует несколько условий, то количество найденных записей может быть большим, а пагинация — не работать корректно из-за особенностей подсчёта общего числа записей.
Проблема в том, что WordPress по умолчанию считает общее количество записей без учёта всех meta-запросов, что приводит к неправильному числу страниц. Это особенно заметно, если вы используете сложные запросы с несколькими условиями.
Для решения этой проблемы можно использовать кастомный подсчёт общего количества записей или применять фильтры, которые корректируют SQL-запрос, чтобы пагинация работала корректно.
Создание WP_Query с meta-записями и правильной пагинацией
Рассмотрим пример, когда нужно вывести посты, у которых есть определённое значение meta-поля, и сделать пагинацию с помощью WP-PageNavi.
Основной код запроса:
$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
$args = [
'post_type' => 'post',
'posts_per_page' => 5,
'paged' => $paged,
'meta_query' => [
[
'key' => 'wppagenavi_custom_field',
'value' => 'some_value',
'compare' => '=',
],
],
];
$query = new WP_Query($args);Здесь $paged — текущая страница, posts_per_page — количество записей на странице, а meta_query фильтрует по значению meta-поля wppagenavi_custom_field.
Вывод постов:
if ( $query->have_posts() ) :
while ( $query->have_posts() ) : $query->the_post();
the_title('<h3>', '</h3>');
the_excerpt();
endwhile;
// Пагинация
if ( function_exists('wp_pagenavi') ) {
wp_pagenavi( ['query' => $query] );
}
else :
echo '<p>Посты не найдены.</p>';
endif;
wp_reset_postdata();Исправление подсчёта общего количества записей для правильной пагинации
Иногда WP_Query возвращает неправильное $query->found_posts, что ломает пагинацию. Для исправления нужно использовать фильтр found_posts или переписать запрос подсчёта.
Пример решения с фильтром:
add_filter('found_posts', 'wppagenavi_fix_found_posts', 10, 2);
function wppagenavi_fix_found_posts($found_posts, $query) {
if ( !is_admin() && $query->is_main_query() && $query->get('meta_query') ) {
global $wpdb;
$sql = "SELECT COUNT(DISTINCT {$wpdb->posts}.ID) FROM {$wpdb->posts} ";
$sql .= "INNER JOIN {$wpdb->postmeta} ON ({$wpdb->posts}.ID = {$wpdb->postmeta}.post_id) ";
$sql .= "WHERE {$wpdb->postmeta}.meta_key = 'wppagenavi_custom_field' ";
$sql .= "AND {$wpdb->postmeta}.meta_value = 'some_value' ";
$sql .= "AND {$wpdb->posts}.post_status = 'publish'";
$found_posts = $wpdb->get_var($sql);
}
return $found_posts;
}Этот фильтр вручную подсчитывает количество записей с нужным meta-условием. Обратите внимание, что если у вас более сложный meta_query или другие параметры, нужно расширить SQL соответствующим образом.
Оптимизация и кеширование результатов запросов с пагинацией
Сложные запросы с meta-записями могут нагружать базу данных и замедлять сайт. Чтобы этого избежать, рекомендуется использовать кеширование. Один из вариантов — кешировать объект WP_Query с помощью Transients API или Object Cache.
Пример кеширования WP_Query:
$cache_key = 'wppagenavi_query_' . md5( serialize($args) . '_page_' . $paged );
$query = get_transient($cache_key);
if ( false === $query ) {
$query = new WP_Query($args);
set_transient($cache_key, $query, 3600); // кеш на 1 час
}Такой подход значительно снижает нагрузку на базу при повторных запросах.
Интеграция с плагином WP-PageNavi
WP-PageNavi отлично подходит для кастомной пагинации. Чтобы использовать его с нестандартными запросами, просто передайте объект WP_Query в параметр query функции wp_pagenavi(), как показано в примере выше.
Если хотите изменить внешний вид пагинации, можно настроить шаблон через фильтр wppagenavi_pagination или файлы плагина.
Вывод и рекомендации
Правильная пагинация для комплексных запросов с meta-записями требует внимания к деталям. Важно не только корректно составить WP_Query, но и убедиться, что подсчёт общего числа записей учитывает все условия. Если использовать WP-PageNavi, нужно передавать в него текущий объект запроса и при необходимости исправлять подсчёт через фильтры.
Также не забывайте оптимизировать запросы с помощью кеширования, чтобы избежать излишней нагрузки на сервер.
Для более удобного управления мета-полями и улучшения производительности советуем рассмотреть плагин Clearfy Pro, который помогает оптимизировать запросы и отключать лишние функции WordPress.