Запрос только закрепленных записей
Я использую следующий запрос, чтобы вывести только закрепленные записи:
<?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

В настоящее время у меня нет закрепленных записей на сайте. Это говорит о том, что в цикле ничего не должно отображаться.
Именно здесь вы ошибаетесь, когда передаете пустой массив в 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();
}
}

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

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