Comment Query Builder
Comment queries by status, type, post and hierarchy — with the "all includes spam" and hierarchical-counts-threads gotchas called out before they ship.
// Generated with WP CodeKit — powered by GrowQuest (https://growquest.io). $query = new WP_Comment_Query(); $comments = $query->query( array( 'status' => 'approve', 'type' => 'comment', 'number' => 10, 'orderby' => 'comment_date_gmt', ) ); if ( $comments ) { echo '<ul class="recent-comments">'; foreach ( $comments as $comment ) { printf( '<li><a href="%1$s">%2$s</a> on %3$s<p>%4$s</p></li>', esc_url( get_comment_link( $comment ) ), esc_html( get_comment_author( $comment ) ), esc_html( get_the_title( $comment->comment_post_ID ) ), esc_html( wp_trim_words( $comment->comment_content, 20 ) ) ); } echo '</ul>'; } else { esc_html_e( 'No comments yet.', 'mytheme' ); }
About this generator
WP_Comment_Query Generator Online
Build a WP_Comment_Query argument array — status, type, the post or post type it is attached to, user or author email, a parent filter, threading, ordering, number and fields — and get back the class with a linked comment list, a get_comments() call feeding wp_list_comments(), or just the args.
A Reference tab restates the query in plain English, lists what each comment status means, and explains how threading changes the shape of the result. Free, no sign-up, and every calculation happens in your browser.
Reviewed Output tested on WordPress 6.8 · PHP 8.3
Why the WP_Comment_Query builder beats a hand-written recent-comments loop
Two defaults decide whether a "recent comments" widget is useful or embarrassing. wp_comments holds pingbacks and trackbacks alongside real comments, so a query with no type filter eventually publishes link spam from a scraper site. And status => all means every status, spam included — not "all public". The generator flags both, plus the threading and counting traps behind them.
Pingbacks kept out of your comment list
A query with no type filter raises a warning naming the consequence — pingbacks and trackbacks appear beside real comments — with a one-click "Only comments" fix. This is the single most common reason a front-end list shows link spam.
status "all" is not "all public"
all includes held, spam and trashed rows. On a front-end template that publishes spam, so it is flagged with an "Only approved" fix, and querying spam deliberately gets a reminder that it belongs on the admin side.
The missing limit is called out
WP_Comment_Query has no default limit, so a query without number returns every comment row on a busy site. That is a warning with a "Limit to 10" fix, and asking for more than a hundred full comment objects gets a memory note.
Threading changes what number counts
With hierarchical set, number limits top-level comments and children come along for the ride — ten threads can be a hundred rows. Combining hierarchical with parent is an error, because one asks for a single level and the other builds the tree.
Counts that stay correct
count => true returns a single integer. Pairing it with number is a warning, since the limit caps the rows counted and makes the total wrong, and pairing it with fields => ids is flagged because the fields argument is ignored entirely.
Input validated before it silently matches nothing
A malformed author_email, a non-numeric user_id and a non-numeric post_id are each errors. Ordering by comment_date gets a nudge toward comment_date_gmt, which sorts consistently across a timezone change, with a one-click fix.
How does the comment query generator work?
Filter by status and type first, then scope it to a post or an author, then decide how the rows come back.
- 01
Set the status and type
Choose
approve,hold,spam,trashorall, then restrict tocomment,pingback,trackbackor leave it open to any type. - 02
Scope the query
Narrow to a single
post_id, to a wholepost_type, to auser_idorauthor_email, or to replies under oneparent. Add a search term if you need it. - 03
Choose the order and shape
Set
orderbyand direction, cap it withnumber, pick full objects orids, decide whether the result is threaded or flat, and togglecount, the comment meta cache andno_found_rows. - 04
Clear the checks, then export
Apply the one-click fixes, then take the class with its linked list, the
get_comments()version that feedswp_list_comments(), or the args array alone.
Worked example — the ten most recent approved comments, no pingbacks
A sidebar list. type => comment keeps trackbacks and pingbacks out, and ordering on comment_date_gmt rather than comment_date keeps the sequence stable if the site timezone ever changes.
$query = new WP_Comment_Query();
$comments = $query->query( array(
'status' => 'approve',
'type' => 'comment',
'number' => 10,
'orderby' => 'comment_date_gmt',
) );
if ( $comments ) {
echo '<ul class="recent-comments">';
foreach ( $comments as $comment ) {
printf(
'<li><a href="%1$s">%2$s</a> on %3$s<p>%4$s</p></li>',
esc_url( get_comment_link( $comment ) ),
esc_html( get_comment_author( $comment ) ),
esc_html( get_the_title( $comment->comment_post_ID ) ),
esc_html( wp_trim_words( $comment->comment_content, 20 ) )
);
}
echo '</ul>';
} else {
esc_html_e( 'No comments yet.', 'mytheme' );
}This list is deliberately flat. Switch hierarchical on and the same arguments produce a tree instead, at which point number starts counting threads rather than comments — the generator warns about that swap when you make it.
WP_Comment_Query — frequently asked questions
The questions behind most recent-comments bugs.
How do I exclude pingbacks and trackbacks from a comment query?
Pass 'type' => 'comment'. Pingbacks and trackbacks are stored in wp_comments as ordinary rows with a different comment_type, so a query that omits the argument returns all three kinds. type__not_in => array( 'pingback', 'trackback' ) is the equivalent if you also have custom comment types to keep.
What does status => all include?
Every status in the table: approved, held for moderation, spam and trashed. It is not a synonym for "everything a visitor may see". On a public template that means spam gets published, so use approve on the front end and reserve all for admin-side tooling.
Why does number not limit my threaded comment list?
With hierarchical set to threaded or flat, number applies to top-level comments only; each one then carries its children. Ten threads with five replies each is fifty-five rows. If you need a hard cap on rows, set hierarchical to false and build the list flat.
How do I count comments without fetching them?
Set 'count' => true and the query returns an integer instead of an array. Leave number unset, because a limit caps the rows counted and produces a wrong total, and note that fields is ignored alongside count. For per-status totals on a whole site, wp_count_comments() is the purpose-built function.
Can I query comments on a specific custom post type?
Yes — pass 'post_type' => 'your-cpt' and the query joins against wp_posts to filter. The post type must have been registered with comments in its supports array, or there will be nothing to find. post_id filters to a single post and takes a numeric ID only.
Should I order by comment_date or comment_date_gmt?
comment_date_gmt for anything you sort or compare. comment_date is stored in the site timezone, so changing that setting reorders historical comments relative to each other; the GMT column is a fixed instant and stays consistent. Use comment_date only when you are displaying a local time to a reader.
Where do I paste the code from the WP_Comment_Query generator?
You have three good options and one bad one. Best is a small site-specific plugin — the generator can output one for you, and it keeps working when you change theme. A code-snippets plugin is fine too. A child theme's functions.php works but ties the code to that theme. Never edit the parent theme: the next update overwrites it and your code is gone.
Can I use the generated code in client work or a commercial plugin?
Yes. The output is ordinary WordPress API calls that you configured — there is no licence attached to it and no attribution required. Use it in client sites, commercial plugins and themes, or products you sell. The generated file carries a short credit comment you are free to delete.
The other Query generators in the library, plus the WordPress tools most often used alongside this one.