Custom WP_Comment_Query with pagination and orderby?

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

Leave a Comment