Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I see many people prefer to use pre_get_posts hook instead of query_posts. The code below works and shows all posts which have meta key "featured"

function featured_posts( $query ) {
    if ( $query->is_main_query() ) {
       $query->set('meta_key', 'featured';
       $query->set('meta_value', 'yes';
    }}
add_action( 'pre_get_posts', 'featured_posts' );

But I want the posts which have 'featured' meta_key to be excluded from the main query. Is there an easy way for this?

share|improve this question

2 Answers 2

I see many people prefer to use pre_get_posts hook instead of query_posts

Yay!

So pre_get_posts filters a WP_Query object which means anything you could do via query_posts() you can do via $query->set() and $query->get(). In particular we can make use of the meta_query attribute (see Codex):

$meta_query = array(
                 array(
                    'key'=>'featured',
                    'value'=>'yes',
                    'compare'=>'!=',
                 ),
);
$query->set('meta_query',$meta_query);

But.. this replaces the original 'meta query' (if it had one). So unless you want to completely replace the original meta query, I suggest:

//Get original meta query
$meta_query = $query->get('meta_query');

//Add our meta query to the original meta queries
$meta_query[] = array(
                    'key'=>'featured',
                    'value'=>'yes',
                    'compare'=>'!=',
                );
$query->set('meta_query',$meta_query);

This way we add our meta query alongside existing meta queries.

You may/may not want to set the relation property of $meta_query to AND or OR (to return posts that satisfy all, or at least one, meta queries).

* Note: This type of query will return posts with the 'featured' meta key, but whose value is not yes. It will not include posts where the 'featured' meta key doesn't exist. You'll be able to do this in 3.5.

share|improve this answer
    
So there is no way to check if a meta_key for a post exists or not / is empty or not? I'll have to wait 3.5. then. Thanks for your reply. –  Carlisle Nov 10 '12 at 12:57
    
I will simply create a meta box with Yes and No options and 'No' will be selected by default. When I want to feature a post I will select Yes. However, I want last 5 posts to stay featured and others go on to display on the main query. I dont want to go back and change the selection everytime so I have to find a way to exclude only most recent 5 posts only. I see many similar questions on stackexchange and there should be an easy way to manage those featured posts. (a way that doesn't affect general performance, doesn't create lots of queries or require mixed sql queries) –  Carlisle Nov 10 '12 at 13:38
    
BTW I'm not sure whether it's a good idea to create an extra meta_key with Yes or No value for all posts. It would be great to exclude those posts which simply lack the featured key. –  Carlisle Nov 10 '12 at 13:44

I want to post my temporary solution for featured posts in case some people may make use of it. I don't use pre_get_posts hook here but not query_posts either. The problem is that I have to play with the main query and have to run a piece of sql query. I would be happy if any experts could check the code and let me know whether it's OK and will not cause any performance issues. It will also be great if anyone has a better approach and share it with us.

Create featured posts query

<?php $featured_query = new WP_query(array('meta_key'=>'featured', 'meta_value'=>'yes', 'posts_per_page' => 5, 'no_found_rows' => true));
while ($featured_query->have_posts()) : $featured_query->the_post(); ?>
Stuff...
<?php endwhile; wp_reset_postdata(); ?>

Create the main query, exclude the posts which has the featured meta_key, limit the exclusion to 5 most recent posts and show all others.

<?php $excludeposts = $wpdb->get_col( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'featured' AND meta_value != '' ORDER BY post_id DESC LIMIT 0, 5" );
$main_query = new WP_Query( array('post__not_in' => $excludeposts, 'paged' => $paged ) );  while ($main_query->have_posts()) : $main_query->the_post();?>
Stuff...
<?php endwhile; ?>
share|improve this answer

Your Answer

 
discard

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.