Query *only* sticky posts

I currently have no posts set as stickies on the website. Which tells me that nothing should show up in the loop.

Exactly where you are wrong when passing an empty array to post__in. WordPress has some silly bugs which has no proper workaround and will most probably stay active bugs for a very long time. This is one of them.

When we pass a valid array of posts ID’s to post__in, we get the following resultant SQL WHERE clause (NOTE: All test are done on a page)

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\')

Now, if we have no stickies, thus passing an empty array to post__in, the following SQL is wrongly generated because the post__in parameter as seen as not set.

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

This is an epic fail with unexpected output. Depending on the parameters you passed you get totally unrelated posts or no posts at all.

That is why you should always validate what you are passing to post__in if the passed values are a dynamic array to avoid this epic failure.

Just another note which might not make any sense at all, if you just need to query sticky posts, always set ignore_sticky_posts to 1 (true). The reason for this is, should you require to not query all the sticky posts or just stickies from a certain category, you get just the ones you need. If you do not ignore stickies, all stickies will be returned regardless of what you have queried (yet another silly bug in my opinion).

You can rewrite your code as follow

$stickies = get_option( 'sticky_posts' );
// Make sure we have stickies to avoid unexpected output
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();    
    }
}

Leave a Comment