Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

Sort posts based on meta value WordPress

Hello,

I want to sort the posts on my site (index-page) based on the meta value. Let me explain the process I've began and what my problem is. Maybe I'm giving out quite a lot of information for a not that big of an issue but I believe it's better to give out more than little.

Currently I use a plugin called [[LINK href="http://wordpress.org/extend/plugins/comment-rating-field-plugin/"]]Comment Rating Field Plugin[[/LINK]]. The plugin allows my visitors to post a rating when commenting. All ratings for each posts are then processed through functions and outputs a meta key (I believe) called [[LINK href="http://i.imgur.com/pMWH4qG.jpg"]]<em>crfp-average-rating</em>[[/LINK]] (click the link to see an image).

Based on <em>crfp-average-rating</em> I want to sort my posts. The post with the best rating gets the top position etc.

So far I've managed to edit my index.php page post order by placing this code above the content loop in index.php:
<?php $posts = query_posts( $query_string . '&orderby=title&order=asc' ); ?>

My idea is to edit this line of code into making my posts being ordered by their meta key value.
I've tried multiple ways but haven't figured out the right way yet. Here's one way I've tried it but it's not working:
<?php $posts = query_posts( $query_string . 'meta_key=crfp-average-rating&orderby=meta_value_number&order=ASC' ); ?>
[[LINK href="http://pastebin.com/Kg6VLmBN"]]Click here to go to pastebin[[/LINK]] to see the line of code in its context (aka index.php on pastebin)

Information you may need:
* [[LINK href="http://mythemeshop.com/themes/greenchili/"]]I'm using the GreenChilli theme by mythemeshop[[/LINK]]
* [[LINK href="http://pastebin.com/Kg6VLmBN"]]The index.php (pastebin) I think I have to edit including my piece of code which I demonstrated above[[/LINK]].
* [[LINK href="http://wordpress.org/extend/plugins/comment-rating-field-plugin/"]]A link to the Comment Rating Field Plugins page[[/LINK]]

Let me know if you can help me out with this problem.

Thanks,
John

Answers (5)

2013-05-10

Navjot Singh answers:

Try changing orderby=meta_value_number to orderby=meta_value_num.

2013-05-10

Jens Filipsson answers:

Change this line:

<?php $posts = query_posts( $query_string . 'meta_key=crfp-average-rating&orderby=meta_value_number&order=ASC' ); ?>

To:

<?php $posts = query_posts( $query_string . 'meta_key=crfp-average-rating&orderby=meta_value_num&order=ASC' ); ?>

2013-05-10

Giri answers:


[[LINK href="http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters"]]http://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters[[/LINK]]

<strong>For integer values</strong>

<?php $posts = query_posts( $query_string . '&meta_key=crfp-average-rating&orderby=meta_value_num&order=asc' ); ?>

<strong>For string values</strong>

<?php $posts = query_posts( $query_string . '&meta_key=crfp-average-rating&orderby=meta_value&order=asc' ); ?>


Johnyay comments:

To some extent your answers seems to work, but not fully. I recently deleted all posts and added 4 new ones. Currently only two posts show when using this code:
<?php $posts = query_posts( $query_string . '&meta_key=crfp-average-rating&orderby=meta_value_num&order=asc' ); ?>

To make more posts appear on the index page it requires me to add a rating through the comments on those posts.

It's hard to say whether it works with the ranking before getting this issue fixed. But I'll do some more testing and see what happens.


Johnyay comments:

Edit: I didn't intend to specifcally reply to Viruthagiri as most of your answers seemed to have been the same.


Giri comments:

Hello Johnyay,

meta field "crfp-average-rating" will not be added to your post until user rate atleast one comment.

So lets add a default value while publish the post.

add_action( 'publish_post', 'default_avg_rating' );
function default_avg_rating( $post_id ) {
add_post_meta($post_id, 'crfp-average-rating', 0);
}


Use that code in your functions.php file


Giri comments:

Little correction..

Use update_post_meta instead of add_post_meta...

So meta value will be updated if already exists. else new one will be created.

add_action( 'publish_post', 'default_avg_rating' );

function default_avg_rating( $post_id ) {

update_post_meta($post_id, 'crfp-average-rating', '0');

}


Johnyay comments:

Added the function you mentioned to my theme functions and now all posts are shown.

The rating system isn't really working as it should though as the post which tops the site right now has only one comment with a 5/5 rating compared to the second post with two comments and with two 5/5 ratings.

It's not that weird though as both has the same average rating - 5. Would it be possible to somehow edit the code to instead make it that the second comments has 10 points because it's been rated 2 times with five stars? This would eventually make the posts being ordered in a more logic order I assume. Maybe that's outside your jurisdiction though.


Giri comments:

Hi I don't fully understand the problem you are having. Could you give me the link to your website.? I'll check it


Johnyay comments:

I would happily disclose the link if I could send it in a private message to you somehow, or the persons only in this thread.

I understand now however it's a problem with how the plugin is used to calculate an average value. This is why:
The first post gets <strong>one</strong> 5/5 rating. The average rating value is <strong>5</strong>
The second post gets <strong>twenty</strong> 5/5 ratings. The average rating value is <strong>5</strong>

Logically the second post would be ranking higher but the script doesn't understand that 20 ratings with 5/5 stars are better than one and therefore ranks the first post higher than the second.

I suppose I'll have to find out a way to edit the plugin to work the way I want or just rank the posts based on how many total ratings they have:
<?php $posts = query_posts( $query_string . '&meta_key=crfp-total-ratings&orderby=meta_value_num&order=desc' ); ?>

And then be able to multiply


Johnyay comments:

Ignore the last 6 words.


Giri comments:

In that case you should also query the number of votes from the database and then sort it.

As you said your first post has 1 votes with average value 5...
Second post has 20 votes with average value 5..

So lets say there is a meta key that stores number of votes.. Lets say its name is "crfp-num-votes".. So you have to order by both numvotes and avg rating..

$posts = query_posts( array( 'post_type'=>'post',
'meta_key'=>'crfp-average-rating',
'orderby'=>'crfp-num-votes crfp-average-rating',
'order'=>'DESC') );


Giri comments:

This is the meta key that stores number of votes..

crfp-total-ratings

[[LINK href="http://plugins.trac.wordpress.org/browser/comment-rating-field-plugin/trunk/comment-rating-field-plugin.php#L121"]]http://plugins.trac.wordpress.org/browser/comment-rating-field-plugin/trunk/comment-rating-field-plugin.php#L121[[/LINK]]

So the query will be

$posts = query_posts( array( 'post_type'=>'post',
'meta_key'=>'crfp-average-rating',
'orderby'=>'crfp-total-ratings crfp-average-rating',
'order'=>'DESC') );


Johnyay comments:

Are you sure that crfp-total-ratings saves total votes? I believe it stores the total reviews/comments made and not the total vote count.

Where do I place the code?

Thanks for getting back.


Giri comments:

I'm not sure.. But just give it a try..

You should replaced my old code with new one...

I mean instead of using this line ..

<?php $posts = query_posts( $query_string . '&meta_key=crfp-average-rating&orderby=meta_value_num&order=asc' ); ?>

use this one

<?php $posts = query_posts( array( 'post_type'=>'post',
'meta_key'=>'crfp-average-rating',
'orderby'=>'crfp-total-ratings crfp-average-rating',
'order'=>'DESC') );
?>


Johnyay comments:

I tried your code and it doesn't work. Maybe the crfp-total-ratings doesn't save the total vote count afterall. I admire your try though.


Giri comments:

Just go to your plugin edit this file

[[LINK href="http://plugins.trac.wordpress.org/browser/comment-rating-field-plugin/trunk/comment-rating-field-plugin.php"]]http://plugins.trac.wordpress.org/browser/comment-rating-field-plugin/trunk/comment-rating-field-plugin.php[[/LINK]]

and add the this code

var_dump($totalRatings);

below this line

http://plugins.trac.wordpress.org/browser/comment-rating-field-plugin/trunk/comment-rating-field-plugin.php#L116

Now refresh your post and see the printed value.. If it matches the number of rated comments in that value then that is the correct meta key


Johnyay comments:

I don't see anything.


Johnyay comments:

Ok. Lets reverse.

This is probably a little bit more complex than being able to change by communicating here.

Right now to get this thing working the only thing I want is to be able to use this piece of code you posted earlier. Meaning. Instead of sorting posts by average votes I'll just sort them by the posts with the most comments in the top.
<?php $posts = query_posts( $query_string . '&meta_key=crfp-total-ratings&orderby=meta_value_num&order=desc' ); ?>


I'm also using this code:
add_action( 'publish_post', 'default_avg_rating' );
function default_avg_rating( $post_id ) {
update_post_meta($post_id, 'crfp-average-rating', '0');
}


Why does I have to place comment with a rating before it shows up on the index-page?


Giri comments:

I have no idea what you are trying to achieve, but I just downloaded that plugin and installed it in my website. Its not working at all. No idea why.. I even switched my theme to twenty eleven and twenty twelve. But still not working..


Johnyay comments:

I remember it was a bit tricky to install as it required some special configurations.

Basically I just want to sort posts by comments (posts with highest comment count first etc). I don't think it'd be required to use the plugin as maybe it's possible to use Wordpress custom functions.

http://pastebin.com/9K5rs0HQ - line 8, that's what I've tried so far but it's not really working.

Maybe there is a function I could add to my functions.php instead to avoid editing core files?


Giri comments:

Try this in your functions.php

add_filter( 'pre_get_posts', 'orderby_comment_count' );
function orderby_comment_count( $query ) {
$query->set( 'orderby', 'comment_count' );
return $query;
}

2013-05-10

Hariprasad Vijayan answers:

The following code will work,

<?php $posts = query_posts( $query_string . '&meta_key=crfp-average-rating&orderby=meta_value_num&order=asc' ); ?>



But the post will not display in the query post result if the meta value for "crfp-average-rating" is empty.

Are sure crfp-average-rating is a meta key?

2013-05-11

DHRUBA BHOWMIK answers:

hello jhonyay

please try it...................


<?php
// Get the requested category object
$category = $wp_query->get_queried_object();
$query = new WP_Query( array ( 'post_type' => 'post', 'cat' => $category->cat_ID, 'order' => 'DESC', 'orderby' => 'meta_value_num', 'meta_key' => '_wti_total_count' ) );
if ( $query->have_posts() ) :
while ( $query->have_posts() ) : $query->the_post();
/* Include the Post-Format-specific template for the content.
* If you want to overload this in a child theme then include a file
* called content-___.php (where ___ is the Post Format name) and that will be used instead.
*/
get_template_part( 'content', get_post_format() );
endwhile;
wp_reset_query();
else:
_e( 'Nothing Found', 'twentyeleven' );
endif;
?>