Make WordPress Core

Opened 31 hours ago

Last modified 16 hours ago

#65313 new enhancement

Extend `WP_Comment_Query` 'fields' parameter to support individual column names

Reported by: dd32's profile dd32 Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version:
Component: Comments Keywords: has-patch has-unit-tests
Focuses: performance Cc:

Description

Background

WP_Comment_Query currently accepts only two values for fields:

  • '' (default) — full WP_Comment objects.
  • 'ids' — comment IDs only.

This is asymmetric with WP_User_Query, which accepts any valid user column as fields (e.g. fields => 'user_email', or an array of column names), returning a flat or shaped result without hydrating WP_User objects.

A common pattern in plugins that build "discussion-style" features on top of comments is to ask "give me the distinct comment_post_IDs where comments match X" — for example, listing posts the current user has commented on, or listing
posts with comments tagged with a particular meta value. Today there are three options, none good:

  1. Use fields => '' and array_column( $query->comments, 'comment_post_ID' ) — hydrates every comment object only to throw all but one field away.
  2. Use fields => 'ids' and then get_comment( $id )->comment_post_ID in a loop — N+1 cache lookups, still O(comments).
  3. Drop to raw SQL — works, but bypasses WP_Comment_Query's filters, caching, and meta-query machinery.

Real-world example

The gp-translation-helpers plugin (translate.wordpress.org) was hydrating ~32K WP_Comment objects per page load for a heavy validator just to extract the distinct post IDs:

<?php
$query = new WP_Comment_Query( array(
    'meta_key'   => 'locale',
    'meta_value' => $locale_slug,
    'user_id'    => $user_id,
) );
$post_ids = array_unique( array_column( $query->comments, 'comment_post_ID' ) );

That call took ~6.6 s on the live database. The equivalent direct SQL returned the same 25,694 distinct post IDs in ~610 ms (an ~11× speedup), purely because it stopped hydrating comments. The plugin had to fall back to raw SQL
(PR #236) for this reason.

Proposal

Allow fields to accept any valid column name from the $wpdb->comments table, matching the WP_User_Query behaviour. At minimum, 'comment_post_ID', 'user_id', and 'comment_parent' are high-value projections.

Suggested API:

<?php
// Returns array of post IDs.
$post_ids = ( new WP_Comment_Query() )->query( array(
    'meta_key'   => 'locale',
    'meta_value' => 'nl',
    'user_id'    => 42,
    'fields'     => 'comment_post_ID',
) );

// Optional: support array of column names, returning stdClass per row.
$rows = ( new WP_Comment_Query() )->query( array(
    'fields' => array( 'comment_ID', 'comment_post_ID', 'comment_date' ),
) );

Backwards compatibility

'ids' and '' (default) keep their current meaning; new column-name values are purely additive.

  • #28434 — original ticket that added the fields parameter (closed/fixed, 2014).

This ticket was drafted with AI, and reviewed before submit

Change History (4)

This ticket was mentioned in PR #11934 on WordPress/wordpress-develop by @dd32.


30 hours ago
#1

  • Keywords has-patch has-unit-tests added

## Summary

Extends WP_Comment_Query's fields argument to accept:

  • A column name from $wpdb->comments (e.g. 'comment_post_ID') — returns a flat array of distinct values for that column.
  • A 'col_a=>col_b' pair (e.g. 'comment_ID=>comment_post_ID') — returns an associative array keyed by col_a's value with col_b's value as the entry, mirroring the 'id=>parent' idiom in WP_Query and WP_Term_Query.

'ids' and '' (default) are unchanged — the new behaviour is purely additive.

## Why

Plugins that want "the distinct comment_post_IDs matching X" have three options today, none good:

  1. fields => '' + array_column( $q->comments, 'comment_post_ID' ) — hydrates every matched comment just to discard all but one field.
  2. fields => 'ids' + get_comment( $id )->comment_post_ID in a loop — N+1 cache lookups.
  3. Drop to raw SQL — bypasses filters, caching, and meta-query.

In the gp-translation-helpers reference case in the Trac ticket, hydrating ~32K comments to extract distinct post IDs took ~6.6s; the equivalent raw SQL returned the same 25,694 IDs in ~610ms (~11x speedup, all of it from skipping hydration).

## API

// Distinct comment_post_IDs — replaces array_unique( wp_list_pluck( ... ) ).
$post_ids = ( new WP_Comment_Query() )->query( array(
    'meta_key'   => 'locale',
    'meta_value' => 'nl',
    'user_id'    => 42,
    'fields'     => 'comment_post_ID',
) );

// [ comment_ID => comment_post_ID ] map — same shape as WP_Query's 'id=>parent'.
$by_id = ( new WP_Comment_Query() )->query( array(
    'post_id' => $post_id,
    'fields'  => 'comment_ID=>comment_post_ID',
) );

Column names must be passed in their exact case. The only exception is the ID suffix of comment_ID / comment_post_ID, which is accepted in any case (comment_id, comment_Id, comment_ID). Unknown columns fall through to the default behaviour (WP_Comment objects), keeping the path forward-compatible.

## Test plan

  • [x] npm run test:php -- tests/phpunit/tests/comment/query.php — 166 tests / 489 assertions pass.
  • [x] npm run test:php -- --group comment — 540 tests / 1367 assertions pass (no regressions).
  • [x] New tests cover:
    • Single-column form returns distinct values.
    • 'col_a=>col_b' map form returns associative array.
    • Case-flexibility of the ID suffix on both sides of =>; strict case for non-ID columns.
    • Unknown column (single + map form) falls back to full WP_Comment objects.
    • 'ids' semantics unchanged.
    • Empty result sets return array() without a follow-up query.
  • [x] phpcs --standard=phpcs.xml.dist clean on both changed files (only pre-existing warnings on untouched lines).

🤖 Generated with Claude Code

This ticket was mentioned in PR #11935 on WordPress/wordpress-develop by @anupkankale.


29 hours ago
#2

…olumn names

  • Accepts a single valid column name (e.g. 'comment_post_ID') and returns a flat array of scalar values
  • Accepts an array of valid column names and returns stdClass objects per row
  • Invalid column names fall back to full WP_Comment objects
  • Existing 'ids' and (default) behaviour unchanged
  • Follows the same pattern as WP_User_Query

Fixes https://core.trac.wordpress.org/ticket/65313

Trac ticket:

## Use of AI Tools

#3 @anupkankale
29 hours ago

PR #11934 by @dd32 covers the same ground with a more complete implementation
including the col_a=>col_b associative map form. Happy to close #11935 in favour
of that PR. Thanks for the quick turnaround on this!

@westonruter commented on PR #11935:


16 hours ago
#4

Thanks for the PR, but I'm closing in favor of #11934 since it lacks coding standards issues while also including unit tests. If you have any suggestions for that PR, please add them there.

Note: See TracTickets for help on using tickets.