Everything In Between

If your project so much as pretends to have a profit motive, I will tell you to go fuck yourself and your project.

Arbitrarily exclude posts from displaying in WordPress

9 comments

When hacking away at WordPress sites, often times you’ll find yourself in a situation where you need to filter out certain posts from displaying on some pages, such as the home page. There are a lot of ways to do this, but few are perfect. Recently, I had the need to do this and went searching for pre-existing solutions.

I came across Vaibhav’s post on the topic and noted that his solution uses the query_posts() function to alter WordPress’s query object before The Loop has run. While this is a great solution if your exclusion criteria is simple enough to be supported directly by the WordPress query object, other times the query_posts() function doesn’t provide you with the hook you need.

In these cases, you can run the original query, note any modifications you need to make, and then create a new, modified query and display the results you get from running that one instead. For instance, you might need to do this if you need to exclude posts based on category and, say, the beginning of their title, or their category and a certain piece of content in the post itself, or all three, or any other combination you can think of.

Another advantage of this technique over simpler ones is that this method maintains the same behavior you’d expect to see in every other way. Most notably, this means that if you’ve told WordPress to display the 10 most recent posts on the home page (in the WordPress settings), you’ll still see ten posts on that page even after you exclude some of them.

To do something like excluding posts if they are in the “Uncategorized” category (traditionally the category with an ID of 1 in WordPress) and their title begins with “Some title”, you can do this:

// original query runs in The (real) Loop first
while ( have_posts() ) : the_post();
    // detect pots matching our exclusion criteria
    if (in_category(1) && (0 === strpos(the_title('', '', false), 'Some title')) ) {
        $wp_query->post_count++; // increment the post counter
        continue;
    }
    endif;
endwhile;
// now make a new query and show the posts for real, with the adjusted post count and filtering
$my_new_query = new WP_Query($query_string.'&showposts='.$wp_query->post_count);
// do another The Loop (and display the results this time)
while ( $my_new_query->have_posts() ) : $my_new_query->the_post();
    // detect and exclude these same posts
    if (in_category(1) && (0 === strpos(the_title('', '', false), 'Some title')) ) { continue; }

// ...the rest of the WordPress template goes here...

This is neat because it gives you the capability to define arbitrarily complex exclusion patterns and directly modify your new query object however you like before you execute it. Once you know this works, you’ll probably want to extract the filtering code into a function. Using the above example, your new code might look like this:

// define criteria for filtering
function matches_filtering_criteria () {
    if (in_category(1) && (0 === strpos(the_title('', '', false), 'Some title')) ) {
        return true;
    } else {
        return false;
    }
}
// original query runs in The (real) Loop first
while ( have_posts() ) : the_post();
    // detect pots matching our exclusion criteria
    if (matches_filtering_criteria()) {
        $wp_query->post_count++; // increment the post counter
        continue;
    }
    endif;
endwhile;
// now make a new query and show the posts for real, with the adjusted post count and filtering
$my_new_query = new WP_Query($query_string.'&showposts='.$wp_query->post_count);
// do another The Loop (and display the results this time)
while ( $my_new_query->have_posts() ) : $my_new_query->the_post();
    //
    // detect and exclude these same posts
    if (matches_filtering_criteria()) { continue; }

// ...the rest of the WordPress template goes here...

For more information on these functions, see:

Written by Meitar

June 6th, 2008 at 1:11 pm

9 Responses to 'Arbitrarily exclude posts from displaying in WordPress'

Subscribe to comments with RSS or TrackBack to 'Arbitrarily exclude posts from displaying in WordPress'.

  1. Meitar Moscovitz,
    I’m confused a little about extracting the code to a function as you wrote.
    Is it as easy as copying and pasting into my functions.php file?
    Or do I still have to put the modified loop into the template?
    Basically I am trying to avoid showing so much duplicate content I do like to have custom templates but also want to have at least one page where everything can be found.But I read that having an archives page is bad for seo.
    Also the site I’m working on is not a blog even though it has a blog and posts appear on the home page(a static page using the loop with a custom query to show a few categories) and the same posts appear on the blog.I’d like to whittle it down to only one category showing on the “blog”.
    Maybe your loop is too much loop for what I need?
    The thing is, I can’t seem to get pagination is I use the get posts tag so I don’t want to use it.
    I guess I need the blog to be a mini blog and the home page to be the “home page blog that isn’t a blog”. If that makes sense I’ll buy you a tea.
    Any help or ideas would be really appreciated!

    mccormicky

    29 Jul 08 at 3:39 AM

  2. @mccormicky:

    You can put the functions in a template file or in the functions.php. It doesn’t really matter as long as the place you put it is in scope so that they run from the template file. The best place is, indeed, probably the functions.php file since that’s the whole purpose of that file. :)

    Also I recently discovered that an update to WordPress 2.6 seems to have broken something in here, but I don’t know what. Maybe this technique doesn’t work anymore….

    Meitar

    30 Jul 08 at 7:38 AM

  3. thanks a lot for this post. Because of this I could fix my theme;)

    mcguillan

    18 Oct 08 at 5:45 PM

  4. Do you have an code example, that show the posts which have no comments? I want to install a place, where people can start a questions and the “comment” is the answer. and i want to list all questions, that have no answer (comment) an idea?

    many thanxs

    cu Till

    Till

    27 Nov 08 at 10:25 PM

  5. @Till: I’m not sure exactly what you’re asking, but you might be interested in checking out the Prologue Theme.

    Meitar

    29 Nov 08 at 8:57 AM

  6. Is it possible exclude post with attachment and display only post with only stories (for example) ?

    Thanks

    Davide

    6 Apr 09 at 6:32 AM

  7. […] 表示から除外する記事 […]

  8. Could you help me to use query_string with post__not_in (pointing to an array ID of post) ???

    Jennifer R

    31 Aug 10 at 8:14 AM

  9. I used your query system to exclude some posts and it worked like a charm. Thanks a million

    Sean

    16 Aug 11 at 9:41 AM

Leave a Reply