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 using custom post types to display properties and have a custom price field assigned to each post. On the property page I want to display a list of four similarly priced properties, two less than or equal to the price of the current property and two greater than the current price. Ordering properties numerically by price is easy enough with wp_query, but how do I only display the closest values to the price of the current property?

share|improve this question

2 Answers 2

up vote 2 down vote accepted

One possibility is a direct SQL query similar to the one given here.

But I'm not convinced that it would be much more efficient than 2 queries, all handled by WordPress:

The is untested

$price =0; //Price of current property
$id=0; //Property (post) ID.

$args = array(
    'post_type' => 'property',
    'post__not_in'=>array($id),
    'posts_per_page'=> 2,
    'meta_query' => array(array(
        'key' => 'price',
        'value' => $price,
        'type' => 'numeric',
        'compare' => '>='
        )),
     'meta_key'=> 'price',
     'orderby'=>'meta_value_num',
     'order'=>'ASC'
    );

 $two_above = get_posts($args);

 //Put their IDs along with current property ID in an array
 $ids = array_values(wp_list_pluck($two_above, 'ID'));
 array_push($ids, $id);

 //Exclude returned properties and current property from next query
 $args['post__not_in'] = $ids;

 $args['meta_query']['compare'] = '<=';
 $args['order'] = 'DESC';

 $two_below = get_posts($args);
share|improve this answer
    
This is great! So far it's working perfectly in my testing. The only thing I changed was to remove the second order arg (DESC) as the ordering stays the same, it's just starting from a different point. Beyond what you have here I just used an array_merge (a first for me) on the output so I could loop through all the posts in one go. All of which makes me very happy. Thanks a ton! –  Sam May 11 '12 at 16:58
    
Glad its working... but are you sure it stays ASC? In the second query you want the first two results to have the highest price, so surely its DESC? –  Stephen Harris May 11 '12 at 17:20
    
So I tested this with more data and found it wasn't working. The code seemed right no matter how I looked at it, so I spent quite a bit of time banging my head against the wall and trying to figure out if other loops were interfering or something. Turns out the solution is pretty simple: the meta_query array needs to contain a additional array. Once I updated the code to reflect that everything worked like a charm. –  Sam Jun 8 '12 at 16:31
    
@Sam You're right! Sorry about that... I've corrected the code. –  Stephen Harris Jun 8 '12 at 19:35
    
No worries. Would not have figured this solution out without you! –  Sam Jun 14 '12 at 18:50

Edit

Thanks for calling me out, it's the only way to get better.

The updated query would look like this:

$args = array(
    'post_type' => 'POST',
    'meta_query' => array(
        'key' => 'PRICE',
        'value' => array( ($price - 2), ($price + 2)),
        'type' => 'numeric',
        'compare' => 'BETWEEN'
        );
    );

Thanks again, kaiser for making me do the right thing.


The quickest thing to do is to create your own query using $wpdb. The most basic function would look like this:

function my_custom_get ($price) {
    global $wpdb;
    $min_price = $price - 2;
    $max_price = $price + 2;

    $sql_query = "
        SELECT $wpdb->posts.* 
        FROM $wpdb->posts, $wpdb->postmeta
        WHERE $wpdb->posts.ID = $wpdb->postmeta.post_id 
        AND $wpdb->postmeta.meta_key = 'PRICE' 
        AND $wpdb->postmeta.meta_value < $max_price
        AND $wpdb->postmeta.meta_value > $min_price
        AND $wpdb->posts.post_status = 'publish' 
        AND $wpdb->posts.post_type = 'PRODUCT'
        AND $wpdb->posts.post_date < NOW()
        ORDER BY $wpdb->posts.post_date DESC
        ";
    return $wpdb->get_results($querystr, OBJECT);
}

Don't forget to change the values of meta_key and post_type to fit your specific application. Hope this helps!

share|improve this answer
1  
A) There's $wpdb->prepare() to make queries safer. B) You can do meta_query and use BETWEEN as comparison value. –  kaiser May 10 '12 at 20:01
    
This would get all properties with a price within +/- the current property's price. The OP wants only 4 properties, whose price is closest to that of the current property - 2 more than, 2 less than. –  Stephen Harris May 11 '12 at 1:50

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.