Leave a Reply

3 comments

  1. 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.

  2. In response @Carlisle, if you want exclude the most 5 recent posts marked featured, you could do the following. Change the posts_per_page to how many you want to exclude, and the meta_query to how you are designating the featured category.

    function cmp_exclude_featured_posts($query) {
        $exclude = array();  //Create empty array for post ids to exclude
        if ( $query->is_main_query() ) {
                $featured = get_posts(array(
                    'post_type' => 'post',
                    'meta_query' => array(
                        array(
                            'key' => 'featured',
                            'value' => '1',
                            'compare' => '==',
                        ),
                    ),
                    'posts_per_page' => 2
                ));
    
                foreach($featured as $hide) {
                    $exclude[] = $hide->ID;
                }   
    
                $query->set('post__not_in', $exclude);
            }
    }
    
    add_filter( 'pre_get_posts', 'cmp_exclude_featured_posts' );
    
  3. 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...
    
    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...
    
    endwhile;
    
    ?>