Excluding Sticky Posts from The Loop and from WP_Query() in WordPress?
-
18-04-2021 - |
Question
The following snippet is from a sidebar widget that lists "recent posts". Since its on the home page and I feature my lastest sticky post prominently on that page, I want to skip over the sticky in this loop. However, the post_not_in=sticky_posts
has no effect.
<?php
$the_query = new WP_Query("showposts=$number&offset=1&order=ASC&post_not_in=sticky_posts");
while ($the_query->have_posts()) : $the_query->the_post();
$do_not_duplicate = $post->ID; ?>
Solution
I took @tnorthcutt's answer from WordPress' Codex on query_posts()
about Sticky Parameters and created a tandalone example you can drop as test.php
into your website's root and see it run by navigating to a URL like this, with your domain substituted:
Some notes on the code; I had to use an array equivalent of the query string you passed to WP_Query()
because the post__no_in
argument can't be passed in as a comma delimited string (not sure why, probably an oversight?).
Also I wanted to make sure you know that starting with an offset=1
(instead of offset=0
) means you'll be excluding the first post that otherwise would be returned by the query. Of course you'll still get the number of posts specified by $number
assuming you have that many applicable posts +1. So here's the code:
<?php
header('Content-Type:text/plain');
include "wp-load.php";
$number = 5;
$the_query = new WP_Query(array(
'showposts' => $number,
'offset' => 1, // This will cause the query to skip over first post
'order' => 'ASC',
'post__not_in' => get_option("sticky_posts"),
));
while ($the_query->have_posts()) : $the_query->the_post();
the_title();
endwhile;
OTHER TIPS
If you want to exclude all sticky posts from a query, use
query_posts(array("post__not_in" =>get_option("sticky_posts")));
(from the codex)
Looks like that will only work on 3.0 or greater, though: http://wordpress.org/support/topic/excluding-sticky-posts-using-query_posts
Edit: in response to your comment below, try this (I'm not sure this will work, but hopefully it will get you started):
<?php
$args=array(
'showposts'=>'$number',
'offset'=>'1',
'order'=>'ASC',
'post__not_in'=>get_option("sticky_posts")
);
$the_query = new WP_Query($args);
while ($the_query->have_posts()) : $the_query->the_post();
$do_not_duplicate = $post->ID; ?>
Travis' answer is fine if you're building your own query, for a secondary loop perhaps, but if you need to modify your main blog query, you can use pre_get_posts to filter out the sticky posts.
In the example below, I'm only excluding the sticky posts if the query is the blog page, as I still want sticky posts to be returned on taxonomy and search pages etc (I'm displaying sticky posts as featured articles on the main news page).
add_action( 'pre_get_posts', 'custom_post_archive_changes' );
function custom_post_archive_changes( $query ) {
if ( is_home() && $query->is_main_query() ) {
// exclude sticky posts from main news page
$stickies = get_option("sticky_posts");
$query->set( 'post__not_in', $stickies );
}
}
Just drop the snippet above in your functions.php file.