pre_get_posts для двух циклов на одной странице

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

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

Я использую следующий код для pre_get_posts.

function tax_and_offset_homepage( $query ) {
 if ( !is_admin() && $query->is_home() && $query->is_main_query() )
  $query->set( 'post_type', array( 'post') );

$ppp = get_option( 'posts_per_page' );
//$ppp = 300;
$offset = 3;

if ( !$query->is_paged() ) {
  $query->set( 'posts_per_page', $ppp);
        $query->set( 'offset', $offset);

 }
} 
add_action('pre_get_posts','tax_and_offset_homepage');

и следующий код для основного цикла:

<?php 
 if ( have_posts() ) {
while ( have_posts() ) {
    the_post(); 
    //
    // Содержимое записи здесь
    //
} // конец while
} // конец if
?>

но проблема в том, что pre_get_posts можно применить только к одному из 2 циклов. Как мне сделать 2 функции pre_get_posts для двух циклов на одной странице?

Посмотрите на WP_Query, когда вам нужно пройтись по записям.

<?php 
  $args = array( 
    'post_type' => 'post',
    'post_status' => 'publish',
    'posts_per_page' => -1,
    'post__not_in' => array(),
    'order' => 'DESC',
  );
  $the_query = new WP_Query($args);

  // Показать первые 3 записи
  while($the_query->have_posts()) { $the_query->the_post(); 
    echo '<h2>'.get_the_title().'</h2>';

    // Мы уже показали 3? Тогда прерываем. (счетчик current_post начинается с 0)
    if( $the_query->current_post == 2 ) { break; }
  }

  // Продолжаем цикл с того места, на котором остановились
  while($the_query->have_posts()) { $the_query->the_post(); 
    echo '<h2>'.get_the_title().'</h2>';
  }

  wp_reset_postdata();
?>

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

Для реализации двух циклов на главной странице WordPress, один из которых будет выводить три последних поста, а другой — оставшиеся посты, вы сталкиваетесь с необходимостью использовать хуки WordPress корректно, без конфликтов между запросами. Ваша текущая реализация pre_get_posts будет действовать только на один из запросов, поэтому необходимо изменить подход к созданию запросов.

Решение проблемы с использованием WP_Query

Вместо того, чтобы полагаться на pre_get_posts, следует использовать класс WP_Query, который предоставит вам большую гибкость в управлении несколькими запросами на одной странице.

Код для реализации двух циклов

Вот пример, как можно организовать ваши запросы с помощью WP_Query:

<?php 
// Настроим параметры для запроса первых трёх постов.
$args_latest = array(
    'post_type'      => 'post',
    'post_status'    => 'publish',
    'posts_per_page' => 3,
    'order'          => 'DESC',
);

// Создаем новый объект WP_Query для последних трех постов.
$latest_query = new WP_Query($args_latest);

// Цикл для вывода первых трех постов.
if ($latest_query->have_posts()) {
    echo '<h2>Последние посты:</h2>';
    while ($latest_query->have_posts()) {
        $latest_query->the_post();
        // Здесь выводим контент поста
        echo '<h3>' . get_the_title() . '</h3>';
        // Можно добавить краткое содержание и ссылку
    }
    wp_reset_postdata(); // Сброс данных после выполнения первого запроса.
}

// Теперь нам нужно взять все остальные посты, исключая те, что мы только что вывели.

$args_remaining = array(
    'post_type'      => 'post',
    'post_status'    => 'publish',
    'posts_per_page' => -1, // Получаем все оставшиеся посты
    'offset'         => 3,   // Смещение на 3 для пропуска уже выведенных постов
    'order'          => 'DESC',
);

$remaining_query = new WP_Query($args_remaining);

// Цикл для вывода оставшихся постов.
if ($remaining_query->have_posts()) {
    echo '<h2>Остальные посты:</h2>';
    while ($remaining_query->have_posts()) {
        $remaining_query->the_post();
        // Здесь выводим контент других постов
        echo '<h3>' . get_the_title() . '</h3>';
        // Можно добавить краткое содержание и ссылку
    }
    wp_reset_postdata(); // Сброс данных после выполнения второго запроса.
}
?>

Краткое объяснение кода

  1. Первый запрос ($latest_query): Запрашиваются последние три поста с использованием параметров $args_latest. Мы выводим их в первом цикле.
  2. Сброс данных поста: После завершения первого цикла, мы используем wp_reset_postdata(), чтобы убедиться, что все глобальные переменные поста сброшены перед следующим циклом.
  3. Второй запрос ($remaining_query): Переменная $args_remaining устанавливает смещение на 3, чтобы пропустить уже выведенные посты. Мы получаем все оставшиеся посты и выводим их во втором цикле.
  4. Использование post_type: Оба запроса устанавливают post_type как post, что указывает на необходимость отображения только типовых постов.

Рекомендации по SEO и производительности

  • Кэширование: Рассмотрите возможность кэширования результатов запросов для улучшения производительности, особенно если ваш сайт имеет большой трафик.
  • Оптимизация SQL-запросов: Постарайтесь не запрашивать слишком много постов одновременно (например, устанавливая posts_per_page в более чем 10), так как это может замедлить работу страницы в зависимости от сложности контента.

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

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

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