Показ правильного количества posts_per_page при избегании использования post__not_in

Вопрос или проблема

WordPress VIP и другие руководства по разработке, которые я видел, рекомендуют избегать использования post__not_in по причинам производительности при использовании WordPress в большом масштабе. Их предложение – фильтровать посты в PHP:

$posts_to_exclude = [ 67, 68, 69 ];

$query = new WP_Query( [ 
    'post_type'      => 'post',
    'posts_per_page' => 5 + count( $posts_to_exclude ),
    'paged'          => get_query_var( 'paged' ),
] );

if ( $query->have_posts() ) :
    while ( $query->have_posts() ) :
        $query->the_post(); 
        if ( in_array( get_the_ID(), $posts_to_exclude, true ) ) {
            continue;
        }
        the_title();
    endwhile;
endif;

Мой вопрос: как показать правильное количество постов на странице, когда фильтруешь посты через PHP? Пример выше добавляет количество исключенных постов к переменной posts_per_page. Однако это приведет к тому, что будет от 5 до 8 постов на странице в зависимости от того, сколько постов исключено для конкретной страницы. Существует ли рабочее решение для того, чтобы количество постов на странице было постоянным, или эта оптимизация действительно предназначена только для постов, которые не будут разбиваться на страницы?

$limit = 5;

if ( $query->have_posts() ) :
    while ( $query->have_posts() ) :
        $query->the_post(); 
        if ( in_array( get_the_ID(), $posts_to_exclude, true ) && $limit > 0 ) {
            continue;
        }
        $limit--;
        the_title();
    endwhile;
endif;

Если вы хотите сохранить лимит posts и избежать параметра post_not_in, вам следует добавить этот код для фильтрации posts в $query.

//получаем посты из объекта запроса
$posts = $query->posts;
//устанавливаем лимит постов, которые вам нужны на странице
$limit = 5; 

//фильтруем по ID, которые вы хотите исключить
$posts = array_filter($posts, function( $data ){ 
    if( ! in_array(  $data->ID, $posts_to_exclude ) )return true;
});

$posts = array_slice($posts, 0, $limit);
//вставляем отфильтрованные посты в объект запроса
$query->posts = $posts;
//здесь вы можете выполнять свой цикл

Правда в том, что, хотя вы определенно можете удалить посты, которые не хотите иметь в своем цикле или после запроса, вы не можете сделать это без нарушений в пагинации. Если вы хотите корректный цикл и пагинацию, вам не удастся обойти post__not_in. Однако, если ваш запрос не такой сложный (как, например, множественные мета-запросы в дополнение к post__not_in), производительность не будет настолько затронута. Конечно, операторы “NOT IN” не самые лучшие, но они не слишком сильно повлияют на производительность вашего сайта.

Так что, пока вам не приходится бороться с медленным временем ответа, вы, вероятно, можете использовать этот один post__not_in 😉

Ответ или решение

Вопрос, который вы задали, касается правильного отображения количества постов на странице при использовании WordPress и избегании параметра post__not_in. Этот вопрос актуален для разработчиков, стремящихся оптимизировать производительность своих сайтов, особенно на больших объемах данных.

Основные Принципы

Использование post__not_in для исключения определённых постов может негативно влиять на производительность базы данных, особенно когда речь идет о масштабных проектах WordPress. Поэтому многие рекомендуют альтернативные решения, которые могут эффективно выполнять задачу исключения постов, не прибегая к этому параметру.

Проблема с Постраничным Отображением

Как вы правильно заметили, простое добавление количества исключаемых постов к переменной posts_per_page приведет к тому, что на странице будет отображаться от 5 до 8 постов, в зависимости от количества исключенных. Это создает несоответствие в пагинации и может сбивать пользователей с толку.

Решение проблемы

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

  1. Установите Лимит: Установите желаемый лимит постов, например, 5.
  2. Инициализируйте запрос: Выполните запрос к базе данных с учетом общего количества постов плюс исключения.
  3. Фильтрация и Проверка: Реализуйте фильтрацию постов в PHP, чтобы отфильтровать те посты, которые нужно исключить, пока не достигнете установленного лимита.

Пример кода:

$posts_to_exclude = [67, 68, 69];
$total_posts_to_show = 5; // Желаемое количество постов на странице

// Получаем все посты с учетом исключений
$query = new WP_Query([
    'post_type' => 'post',
    'posts_per_page' => $total_posts_to_show + count($posts_to_exclude),
    'paged' => get_query_var('paged'),
]);

$filtered_posts = [];
if ($query->have_posts()) {
    // Фильтруем посты и добавляем их в массив
    while ($query->have_posts()) {
        $query->the_post();
        if (in_array(get_the_ID(), $posts_to_exclude, true)) {
            continue; // Пропускаем исключённые посты
        }
        $filtered_posts[] = get_the_ID();

        // Прерывание, если достигли лимита
        if (count($filtered_posts) >= $total_posts_to_show) {
            break;
        }
    }
}

// Завершаем цикл с фильтрованными постами
foreach ($filtered_posts as $post_id) {
    setup_postdata(get_post($post_id));
    the_title();
}
wp_reset_postdata();

Объяснение кода

  1. Запрос: Мы выполняем запрос на получение постов с учетом желаемого количества плюс количество исключаемых постов.
  2. Фильтрация: Мы проходим по всем постам и добавляем только те из них, которые не входят в список исключений.
  3. Пагинация: Таким образом, мы обеспечиваем постоянное количество постов на странице и избегаем проблем с пагинацией.

Заключение

Хотя метод исключения постов через массивы в PHP и может показаться более сложным, его использование имеет смысл при необходимости оптимизации производительности. Однако стоит помнить, что если вы работаете с множественными мета-запросами или ищете простые решения, использование post__not_in может быть менее затратным в плане производительности. Если же у вас возникают проблемы с временем отклика сайта, тогда лучше рассмотреть возможность использования post__not_in, если это позволит сохранять производительность.

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

Оцените материал
Добавить комментарий

Капча загружается...