WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm currently using the code below to list sticky posts on my index.php.

However, when no sticky posts are present, its loading the latest posts (up to the number specified in "settings > reading > blog posts show at most _ posts".

How can I alter the script so that if there are no sticky posts, it exits out of the while?


if (have_posts()) :
while (have_posts()) : the_post();
share|improve this question
up vote 1 down vote accepted

That is because get_option will return an empty array if there are no sticky posts and the query will default to everything.

$sticky = get_option('sticky_posts');
if (!empty($sticky)) {
  $args['post__in'] = $sticky;
  $qry = new WP_Query(array('post__in' => $sticky));
  if ($qry->have_posts()) :
    while ($qry->have_posts()) : $qry->the_post();
      echo $post->post_title;

And please don't use query_posts.

share|improve this answer
Oh, and as yet another aside, +1 to you and Mr. Scholz, obviously (I ain't in no competition). Good night. – Johannes Pille Apr 17 '13 at 23:27

Ask for the existence of sticky posts, before you query the database:

$stickies = get_option('sticky_posts');

if ( $stickies )
    // fetch posts

And please read When should you use WP_Query vs query_posts() vs get_posts()? :)

share|improve this answer

For starters, before we get to the essential issue, there is never hardly ever a reason to use query_posts. It should be treated as if deprecated - mostly anyway.

It does not reset, but overwrite the main query after that has already been executed anyway.

Much rather, use either the get_posts function or a new instance of the WP_Query class:

$args = array(
    'post__in' => get_option( 'sticky_posts' ),
    'post_status' => 'publish'

$stickies = new WP_Query( $args );

if ( $stickies->have_posts() ) {
    while ( $stickies->have_posts() ) {
        // do something

// reset the $post global to its previous state

If, regardless of whether sticky posts were found, you'd like to alter the main query to return nothing (on the home page), make use of the pre_get_posts action:

function wpse_96219_nothing_on_home( $query ) {
    if ( is_home() ) {
        $query->set( 'posts_per_page', 0 );
add_action( 'pre_get_posts', 'wpse_96219_nothing_on_home' );
share|improve this answer
This solution has the same problem as noted in the question-- "when no sticky posts are present, its loading the latest posts". I tested it. $stickies will have posts, but if there are no "sticky" post those posts will be the most recent ones. – s_ha_dum Apr 17 '13 at 22:54
For real, @s_ha_dum? Granted, I did not test this and wrote it up as the last deed of the day before hitting the pillow - but with pre_get_posts in place and returning void when on the main blog page - shouldn't that do it? – Johannes Pille Apr 17 '13 at 22:58
What's the logic behind the function name? Are the numbers just a way to reduce the chances of the same name being used elsewhere? – Dominic Apr 17 '13 at 22:59
@s_ha_dum I suppose I was thinking "filter" when I mistakenly thought returning nothing would suffice. Anyhoo, I altered it to what I believe should now do it, which, given yours and toschos answer is somewhat redundant, but what the hell - hurt, it can't. And as a sidenote, Dominic, yes, the function name is simply meant to reduce chance of causing conflict when verbosely copied. – Johannes Pille Apr 17 '13 at 23:17

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.