Using categories & “stickyness” together

The question:

I’ve got a custom query on my homepage showing all posts in a certain category. I need this query to respect sticky posts, but it seems from my research that category queries ignore stickyness. My question is two (and a half) fold:

  1. Can anyone tell me where/how in the database stickyness is applied to a post? I don’t see it in wp_postmeta or wp_posts. This one is most important and will probably be enough to get you the win accepted answer.
  2. Is there any simple elegant way to grab sticky posts only from a certain category?
  3. If not, then how about an ugly way to do it?

Just for the heck of it, here’s my query, though I think it won’t make a difference to the answer.

$getHighlights = array(
    'posts_per_page' => 7,
    'post_type' => array('post','Event'),
    'category_name' => 'Highlights', 
);

Sorry for the long title, but I wanted to be clear what I was asking for.

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

Just add 'post__in' => get_option('sticky_posts') to your query, to confine your query to only sticky posts. So,

$getHighlights = array(
    'numberposts' => 7,
    'post_type' => array('post','Event'),
    'post__in' => get_option('sticky_posts'),
    'category_name' => 'Highlights'
);

should work for you.

Edit: This is how you can merge two arrays to get the sticky posts at the top of your query:

$getHighlights_sticky = get_posts( array(
        'numberposts' => 7,
        'post_type' => array('post','Event'),
        'post__in' => get_option('sticky_posts'),//it should be post__in but not posts__in
        'category_name' => 'Highlights'
    ));
$getHighlights_other = get_posts( array(
        'numberposts' => 7 - count( $getHighlights_sticky ),
        'post_type' => array('post','Event'),
        'post__not_in' => get_option('sticky_posts'),//it should be post__not_in but not posts__not_in
        'category_name' => 'Highlights'
    ));
foreach ( array_merge( $getHighlights_sticky, $getHighlights_other ) as $post ) {
    setup_postdata( $post );

    // your display loop

}

This will show 7 posts, with the stickies at the top (of course, this is assuming you don’t have more than 7 stickies, otherwise it’ll be all messed up…) (edited to use numberposts as per OP’s comment below…)

Method 2

Sticky is not saved per post, there is sticky_posts option that holds array of such. So you can fetch that with $sticky_posts = get_option('sticky_posts');

See Sticky Post Parameters in Codex for details on querying stickies.

I am not entirely sure what would be the best approach to make your query respect stickies. From quick look at code it’s likely is_home conditional gets overridden and that kicks stickies off. Might be able to hook somewhere and fake that conditional, but this might break something further in processing.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment