Запрос только закрепленных записей

16 сент. 2015 г., 22:21:27
Просмотры: 22.2K
Голосов: 5

Я использую следующий запрос, чтобы вывести только закрепленные записи:

<?php
    $args = array(
        'post_type' => 'post',
        'posts_per_page' => 2,
        'post__in' => get_option('sticky_posts')
    );
?>

<?php query_posts($args); ?>
<?php if(have_posts()) : ?>

    <?php get_template_part('loop', 'feed-top-stories' ); ?>

<?php endif; ?>
<?php wp_reset_query(); ?>

На сайте у меня нет записей, отмеченных как закрепленные. Это означает, что в цикле ничего не должно отображаться. Однако я обнаружил, что он все равно выводит 2 записи (хотя они не были закрепленными)

Затем я переключился на объект WP_Query (так как мне ранее советовали избегать использования query_posts())

<?php

    $args = array(
            'post_type' => 'post',
            'post__in' => get_option( 'sticky_posts' ),
            'posts_per_page' => 2
    );

    $the_query = new WP_Query($args);

    if ( $the_query->have_posts() ) : while ( $the_query->have_posts() ) : $the_query->the_post();

        get_template_part('loop', 'feed-top-stories' );

    endwhile; endif;

    wp_reset_postdata();

?>

Но теперь это, похоже, не работает вообще: цикл выводит 2 записи, но обе они являются просматриваемой страницей, несмотря на установленный параметр post_type

4
Комментарии

@PieterGoosen это не решает мою проблему... хотя я не понимаю, как игнорирование sticky posts может помочь?

User User
17 сент. 2015 г. 00:13:51

Sticky posts автоматически добавляются в запрос, поэтому я понимаю, почему Pieter предложил их игнорировать, так как вы также явно запрашиваете sticky posts. Я предлагаю посмотреть на $the_query->request после выполнения запроса, чтобы увидеть сгенерированный SQL, возможно, у вас есть какой-то некорректно настроенный фильтр, который вмешивается.

Milo Milo
17 сент. 2015 г. 00:33:59

@Milo а, понятно! Спасибо. Я попробовал это сделать и, хотя я не эксперт по SQL, могу сказать, что запрос не очень похож на тот, который я пытаюсь сделать? (Я размещу его под этим комментарием)

User User
17 сент. 2015 г. 16:45:46

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 0, 2

User User
17 сент. 2015 г. 16:45:54
Все ответы на вопрос 1
2
16

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

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

Когда мы передаем действительный массив ID записей в post__in, мы получаем следующий результирующий SQL WHERE (ПРИМЕЧАНИЕ: Все тесты проводятся на странице)

AND wp_posts.ID IN (59,45) 
AND wp_posts.post_type = \'post\' 
AND (wp_posts.post_status = \'publish\' OR wp_posts.post_status = \'private\')

Теперь, если у нас нет закрепленных записей, и мы передаем пустой массив в post__in, генерируется неправильный SQL, потому что параметр post__in воспринимается как не установленный.

AND wp_posts.ID IN (59) 
AND wp_posts.post_type = \'post\' 
AND (wp_posts.post_status = \'publish\' OR wp_posts.post_status = \'private\')

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

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

Еще одна заметка, которая может не иметь смысла: если вам нужно запрашивать только закрепленные записи, всегда устанавливайте ignore_sticky_posts в 1 (true). Причина в том, что если вам нужно запросить не все закрепленные записи или только записи из определенной категории, вы получите именно те, которые вам нужны. Если вы не игнорируете закрепленные записи, все закрепленные записи будут возвращены независимо от вашего запроса (еще одна глупая ошибка, по моему мнению).

Вы можете переписать свой код следующим образом:

$stickies = get_option( 'sticky_posts' );
// Убедимся, что есть закрепленные записи, чтобы избежать неожиданного вывода
if ( $stickies ) {
    $args = [
        'post_type'           => 'post',
        'post__in'            => $stickies,
        'posts_per_page'      => 2,
        'ignore_sticky_posts' => 1
    ];
    $the_query = new WP_Query($args);

    if ( $the_query->have_posts() ) { 
        while ( $the_query->have_posts() ) { 
            $the_query->the_post();

            get_template_part('loop', 'feed-top-stories' );

        }    
        wp_reset_postdata();    
    }
}
8 февр. 2016 г. 20:31:36
Комментарии

"Еще одно замечание, которое может показаться бессмысленным: если вам нужно запросить только закрепленные записи, всегда устанавливайте ignore_sticky_posts в 1 (true). Причина в том, что если вам потребуется не запрашивать все закрепленные записи или только закрепленные из определенной категории, вы получите именно те, которые нужны. Если не игнорировать закрепленные, будут возвращены все закрепленные записи, независимо от вашего запроса (еще одна глупая ошибка, на мой взгляд)."

И даже если вы это сделаете, параметр post__not_in все равно становится бесполезным.

lucian lucian
14 авг. 2016 г. 14:22:51

Вау, это очень полезно. Спасибо! Мой запрос был для показа закрепленных записей вверху постов каждой категории, и все работало нормально, пока я не столкнулся с ситуацией, когда на всем сайте не было ни одной закрепленной записи. Ваше предложение использовать условие для get_option( 'sticky_posts’ ) оказалось именно тем, что мне было нужно.

Joel Farris Joel Farris
18 нояб. 2021 г. 04:45:58