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'm trying to set up a search page that first shows a Loop with all posts with a Custom Field meta_key of 'seek_premium' where it's meta_value is 'yes', and then a second Loop where the meta_value (same meta_key) is empty. I've got it working for the most part, but the way I'm doing it seems to break the default search functionality, in that if I do a search, no matter if a post contains the search query or not, I end up seeing all posts marked as "seek_premium" in the first loop, and all posts where "seek_premium" is empty in the second. Here's my code:

<?php if ( have_posts() ) : ?>
    <h1>My Heading</h1>
    <?php
        $premium_query = new WP_Query( array( 'meta_key' => 'seek_premium', 'meta_value' => 'yes' ) );
        while ( $premium_query->have_posts() ) : $premium_query->the_post(); 
            $seekpremium = get_post_meta( $post->ID, 'seek_premium', true );
    ?>
            SHOW PREMIUM POSTS                                                                                  
        <?php endwhile; ?> 
    <?php
        $free_query = new WP_Query( 'post_per_page=50' );
        while ( $free_query->have_posts() ) : $free_query->the_post();
            $seekpremium = get_post_meta( $post->ID, 'seek_premium', true );
            if ( !empty( $seekpremium ) )
                continue;
    ?>
            SHOW FREE POSTS                                                     
        <?php endwhile; ?> 
<?php else : ?>
    <?php include ( TEMPLATEPATH . "/unknown.php" ); ?>
<?php endif; ?>

Anyone have any ideas? I'd seen something about using $is_search as a parameter, but either am not implementing it correctly or something else with my query is wrong...

share|improve this question
add comment

4 Answers 4

Alright, I just whipped something up, this should do it, but it's untested.

<?php
    $premium_args = array(
        'post_status' => 'publish',
        'meta_query'  => array(
            array(
                'key'   => 'seek_premium',
                'value' => 'yes'
            )
        )
    );
    $premium_posts = new WP_Query( $premium_args );
?>
<?php foreach( $premium_posts as $p ) : ?>
    Your output here
<?php endforeach; ?>

<?php
    $free_args = array(
        'post_status' => 'publish',
        'meta_query'  => array(
            array(
                'key'     => 'seek_premium',
                'value'   => 'yes',
                'compare' => '!='
            )
        )
    );
    $free_posts = new WP_Query( $free_args );
?>

<?php foreach( $free_posts as $p ) : ?>
    Your output here
<?php endforeach; ?>

<?php if( 0 == count( $premium_posts ) && 0 == count( $free_posts ) ) : ?>
    No results
<?php endif; ?>

I also feel like that's a lot easier to read and to follow than your current code, so if you get both working, usually the best practice is to go with the one that's most readable. Naturally, with this you can implement have_posts() and such, but I just wanted to get the general idea across, namely using meta_query.

share|improve this answer
    
Okay that seems to have solved the trick, m0r7if3r, as far as the results being limited to the actual search query...but it's giving me duplicate results. Each results is being displayed multiple times, and it's showing them in both the premium and free loops... –  Nathan Jan 24 '12 at 15:05
    
As in the meta query is not working and you are getting premium posts in the free loop, or as in your output is borked? –  m0r7if3r Jan 24 '12 at 21:48
    
It was showing the correct results, in that they were limited to the keywords, but say RESULT A matched the keywords, well it was showing RESULT A in the Premium section about 20 times and RESULT A in the Free section too, also 20 times. In this instance, RESULT A was not Premium. –  Nathan Jan 25 '12 at 16:44
    
Did you do a print_r() on the results, or any other sort of troubleshooting? –  m0r7if3r Jan 25 '12 at 18:52
add comment

Try this once and see if it makes a difference:

<?php if (have_posts()) : ?>
<h1>My Heading</h1>
<?php $premium_query = new WP_Query(array('meta_key' => 'seek_premium', 'meta_value' => 'yes' ));
while ($premium_query->have_posts()) : $premium_query->the_post(); 
$seekpremium = get_post_meta($post->ID, 'seek_premium', true); ?>
SHOW PREMIUM POSTS                                                                                  
<?php endwhile; wp_reset_postdata(); ?> 
<?php $free_query = new WP_Query('post_per_page=50');
while ($free_query->have_posts()) : $free_query->the_post(); 
$seekpremium = get_post_meta($post->ID, 'seek_premium', true); 
if ( !empty( $seekpremium ) ) 
continue; ?>
SHOW FREE POSTS                                                     
<?php endwhile; ?> 
<?php else : ?>
<?php include (TEMPLATEPATH . "/unknown.php"); ?>
<?php endif; ?>

I added in wp_reset_postdata() in there which (to quote the Codex) does this: "After looping through a separate query, this function restores the $post global to the current post in the main query." Didn't test this though, just thought I would throw that out there.

share|improve this answer
add comment

This is really easy to do with only one query and one loop. Change your query to order by your meta key...

add_filter('request', 'check_requests_for_search' );
function check_requests_for_search( $request ) {
    $dummy_query = new WP_Query();
    $dummy_query->parse_query( $request );
    if ( $dummy_query->is_search() ) {
        $request['orderby'] = 'meta_value menu_order title';
        $request['meta_key'] = 'seek_premium';
        $request['order'] = 'DESC';
    }
    return $request;
}

Note that I've ordered second by menu_order and then title here, just since that seems fairly logical. Anyway, this allows you to have normal pagination, and everything should continue to work as expected.

If you want to split the sections up, you can still do that in the one loop; put an if-clause in the loop that checks for when the value of seek_premium changes.

Cheers~

share|improve this answer
    
I'm trying to implement this, Matthew, as this would be the ideal solution. I was actually wanting to sort by two different factors anyway. However, this doesn't seem to be sorting correctly either. Could it be because "seek_premium" either has a value (yes) or no value at all (it's toggled via a checkbox in WP post editor)? –  Nathan Jan 24 '12 at 15:12
    
You might change the 'order' to 'ASC' -- I couldn't remember which way it should go. If it's not spitting them in reverse, how is it ordering them? –  Matthew Boynes Jan 24 '12 at 15:23
    
Maybe I'm implementing it wrong, Matthew. Could you perhaps be a little more specific on where / how to add that code in the loop? –  Nathan Jan 24 '12 at 15:34
    
I just replicated your setup and I see your issue. The way WP crafts the SQL, if the value is null the post won't be included in the result... hmm, The two easiest ways around it would be to either set seek_premium to 'No' on save if the checkbox isn't checked, or to add a hidden field above the checkbox with a value of No, e.g. <input type="hidden" name="seek_premium" value="No" />. I think perhaps in this situation, running two queries is probably the better of two evils as that will be safer. –  Matthew Boynes Jan 24 '12 at 15:54
    
See below answer: Meta Query args. –  kaiser Jan 24 '12 at 18:34
add comment
up vote 0 down vote accepted

I've found what I needed here: http://deadlyhifi.posterous.com/separate-posts-and-pages-in-wordpress-search

Essentially, I needed to know how to maintain the basic query WP generated (so it knew to keep it as a search result vs. just executing the exact query I was calling in the search.php file).

Thanks everyone for your input!

share|improve this answer
add comment

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.