4

I'm trying to setup a custom WP_Comment_Query which is ordered by a meta key. (It might be worth mentioning that these comments are being retrieved with AJAX.)

It all works fine, until I add in pagination into the query args.

$orderby = 'top-comments';

$args = array(
    'post_id' => $post_id,
    'type' => 'comment',
    'status' => 'approve',
    'hierarchical' => true
);

if ( $orderby == 'top-comments' ) {
    $args['meta_key'] = 'comment_rating';
    $args['orderby'] = 'meta_value_num';
    $args['order'] = 'ASC';
}

// $comments_query = new WP_Comment_Query;
// $comments = $comments_query->query($args);

// Works fine up until I add the pagination args

$number = 5;
$paged = 1;

$args['number'] = $number;
$args['paged'] = $paged;

$comments_query = new WP_Comment_Query;
$comments = $comments_query->query($args);

// Gets the 5 latest comments, then orders those by meta_key

The results without the pagination args works perfect, and orders the comments exactly how I want it.

However, once the number argument is set, it will retrieve the newest 5 comments, and then order them by meta_key => 'comment_rating'.

The behaviour I expect is WP_Comment_Query first applying the orderby, and then returning the top 5 results.

What am I doing wrong?

  • 1
    You can't set both paged and offset, because paged uses offset internally. – Milo Apr 17 '17 at 16:17
  • @Milo Issue still persists, but thanks for letting me know! I removed it from the question to avoid confusion. – Swen Apr 17 '17 at 20:15
4

The goal was to paginate comments, showing comments with the highest comment_rating meta value first.

Thanks to the answer of cjbj and the comments by Milo and birgire I figured out the rather unintuitive solution to the issue.

By using numberand offset I was able to make the results in the proper order, but pagination was strange, and each 5 posts were seemingly "flipped" on every page.

Here is my workaround, resulting in a list of comments, starting with the highest rated first, and the lowest rated last.

$orderby = 'top-comments';

$args = array(
    'post_id' => $post_id,
    'type' => 'comment',
    'status' => 'approve',
    'hierarchical' => true
);

if ( $orderby == 'top-comments' ) {
    $args['meta_key'] = 'comment_rating';
    $args['orderby'] = 'meta_value_num';
    $args['order'] = 'ASC';
}

// 5 Comments per page
$comments_per_page = $number = 5; 

// Get the comment count to calculate the offset
$comment_count = wp_count_comments($post_id)->approved;

// Currently page 1 (set with AJAX in my case)
$page = 1;

// Rather unintuitively, we start with the total amount of comments and subtract
// from that number 
// This is nessacary so that comments are displayed in the right order
// (highest rated at the top, lowest rated at the bottom)

// Calculate offset
$offset = $comments_count - ($comments_per_page * $page);

// Calculate offset for last page (to prevent comments being shown twice)
if ( $offset < 0 ) {
    // Calculate remaining amount of comments (always less than 5)
    $comments_last_page = $comments_count % $comments_per_page;

    // New offset calculated from the amount of remaining comments
    $offset = $offset + $comments_per_page - $comments_last_page;

    // Set how many comments the last page shows
    $number = $comments_last_page; 
}

// Then we pass the $number and the $offset to our query args
$args['number'] = $number;
$args['offset'] = $offset;

$comments_query = new WP_Comment_Query;
$comments = $comments_query->query($args);

// Result: 5 comments, starting with the highest rating at the top, and the
// lowest rated at the bottom
2
+50

If you take a look at the wp_comment_query class, you'll see there is no parameter paged. If you then look at wp_list_comments, which does allow pagination, you'll see that it calls a lengthy walker function to achieve comments pagination.

So, it you want to do comments pagination yourself, you're up to some nontrivial programming. The basis will be the number and offset parameters available with wp_comments_query. If you want five comments per page you will need parameters like this:

page 1: offset=0, number=5
page 2: offset=5, number=5
page 2: offset=10, number=5

Basically, you'll have to get the page from the query_var of your page, then calculate the desired offset. Beware that there also is no max_num_pages parameter in wp_comment_query, so it will be difficult to know how many comments there are in your selection.

It might be easier to just retrieve the full comment list every time and solve the pagination in PHP rather than in the query.

  • 2
    Ticket #38268 has a patch adding a support for the paged argument. We can also peek into comments_template() to see how it's handled with offset: $comment_args['offset'] = ( $page - 1 ) * $per_page; where $page = (int) get_query_var( 'cpage' ); – birgire Apr 18 '17 at 8:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.