6

I am aiming to pagination WP_Comment_Query(). It appears this is either taboo or there is no viable information about it online, not anything.

Why? Is it possible? If so, how?

9

Yes, it is possible, but it is a bit of a pain.

Looking at the codex page, only arguments of note are number and offset.

We need these two to create our paginated pages.

First, we set the $paged parameter, which is the current page:

$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;

Then number of comments to display:

$number = 3;

After that, calculate the offset (where the query begins pulling comments):

$offset = ( $paged - 1 ) * $number;

Let's place them all in the arguments variable:

// arguments to filter comments
$args = array(
    'number' => $number,
    'offset' => $offset,
    'paged' => $paged
);

Now let's hit the query and loop through it:

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

// Comment Loop
if ( $comments ) {

    foreach ( $comments as $comment ) {
        echo '<p>' . $comment->comment_content . '</p><br><br>';
    }

} else {

    echo 'No comments found.';

}

Excellent. Now we can test to add /page/2 to the URL bar to check if it works, which it does.

The only thing missing is adding pagination links, for example, the next_posts_link() function.

The problem is that I have not found a way to get max_num_pages. The following would normally work in a simple WP_Query:

$the_query->max_num_pages

But it does not work here. Without knowing the maximum amount of pages, we cannot create our pagination links properly. Note that count($comments) will give us only the total amount of comments per page ($number).

Personally, I fixed this by calculating the maximum pages by the custom query I was targetting. I wanted to get the total amount of comments by User ID. So I used that number like this:

$maximum_pages = $user_total_comments / $number;

This works in my case, but we definitely need a way to get max_num_pages. Hopefully, with this answer, it will inspire someone to solve the final bit. At least we have a lot more information about pagination with wp_comment_query() here than anywhere else.

Update

So the remaining problem was the lack of max_num_pages. One way to solve this is to count() the returned array of post and check if it matches with the $number (what you set in the number array key), see below:

$tot_returned_comments = count($comments);

if ($number == $tot_returned_comments) {
    echo '<a href="/comments/page/' . $nextpage . '">Next</a>';
}

This works in all cases besides if the final page has the exact same amount of posts as you set in your $number variable. So, if you set $number to 15, and your final paginated page has 15 results, then it will display the next button.

Now, if you do not care about performance, you could easily just run two queries. One where you do not limit the results and simply count() the results and use that count for the max_num_pages value.

While this doesn't solve the lack of getting max_num_pages, it should be enough to get you on your feet with a fully working pagination for wp_comments_query().

  • Just a FYI paged param seems like is useless as with offset and number seem enough. Thank you. – Crisoforo Gaspar Jul 12 '17 at 3:35
  • 1
    I had the same problem. It turns out that $the_query->max_num_pages is available along with $the_query-> found_comments by add the following to the arguments: 'no_found_rows' => false With both the max number of pages and found results, it's easy to write any custom pagination. – DGStefan Sep 17 '18 at 14:51
3

The alternative way to handle this problem is to use paginate_links() with get_comments() (or any similar query). Specifically to get the equivalent of max_num_pages, you can use the built-in function wp_count_comments().

So, to get your maximum number of pages, you'd first produce a count of all the comments you want. Presuming you don't want unapproved comments:

$all_comments = wp_count_comments();
$all_comments_approved = $all_comments->approved;

It's a simple matter to divide $all_comments_approved by the number of comments per page. So, with a desired "n" comments per page:

//Adding one at the end as simple way of rounding up. 

$max_num_pages = intval( $all_comments_approved / $comments_per_page ) + 1;  

(The value of $comments_per_page should be pre-set as > 0, and is also used in the main comment query - see below).

The full pagination function will look something like the following, depending on other particulars. (For example: Sometimes the 'base' option will be made trickier by the presence of query variables in the URL. I had to use a preg_replace to get around that problem in one application.)

$current_page = max(1, get_query_var('paged'));

echo paginate_links(array(
        //check codex for how to work with get_pagenum_link and variations
        'base' => get_pagenum_link(1) . '%_%',
        'current' => $current_page,
        'total' => $max_num_pages,
        'prev_text' => __('&laquo; Previous'),
        'next_text' => __('Next &raquo;'),
        'end_size' => 2,
        'mid-size' => 3
));

...and the rest is formatting the output... and the main comment query. The latter will look like the following: Note that $comments_per_page is critical here both for the number of comments retrieved and for calculating the offset. Note also that the total size of the object retrieved is limited by the number (as well as by 'status').

$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$offset = ($paged - 1) * $comments_per_page;


$comments = get_comments(array(
'status' => 'approve',
'number' => $comments_per_page,
'offset' => $offset
));
  • This is lovely stuff, thanks for posting. Although do you have a solution for pagination with WP_Comment_Query() which this question was originally asking? A solution that's different to mine that is. My solution is just about complete, I was just experiencing one minor hickup as you can read in my Update part at the end of the answer. – Christine Cooper Sep 2 '15 at 0:02
  • In a way, this does, since get_comments() uses WP_Comment_Query: So what you do to WP_Comment_Query may be re-inventing the wheel. See: core.trac.wordpress.org/browser/tags/4.3/src/wp-includes/… Also just noticed there's a simple get_approved_comments() that I may be substituting for the above two-line prprocess in the future: core.trac.wordpress.org/browser/tags/4.3/src/wp-includes/… – CK MacLeod Sep 2 '15 at 1:20
  • Also, am not entirely clear on the hiccup. Is it that you don't like running multiple queries? I'm not sure how much this adds to overhead, since you're retrieving a relatively small small object. Have not noticed problems where I've used derivations of this function. Maybe it's an issue with VERY high-traffic sites: I don't know (and would be happy to be enlightened on the matter!). – CK MacLeod Sep 2 '15 at 1:28
  • Sorry for the lack of clarification. I was referring to my own solution posted in the other answer, the the part where I discuss "besides if the final page has the exact same amount of posts as you set in your $number variable..." No big deal though. Thanks again for posting this, it offers an alternative solution for users who go with get_comments() function. +1 – Christine Cooper Sep 2 '15 at 15:26
  • Ah - I see. Just verified in my test environment that that's a problem... If you do count all comments, it's easy to prevent that last bad "next" or final blank page by testing "paged" vs "max_num_pages." That's something I've neglected to do in my own work and will handle! Without the value for max_num_pages, then I think you'd have to work out a different scheme that might get a little complicated, introducing a hitch in the comment-echoing foreach cycle allowing for a check for existence of next comment (or change in iterator) before echoing the pagination "next." Seems unnecessary. – CK MacLeod Sep 2 '15 at 16:18

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.