Skip to content

Query: Allow WP_Query to select specific post fields. - #15499

Open
JDeepD wants to merge 1 commit into
WordPress:trunkfrom
JDeepD:fix/54378-quick-edit-parent-dropdown
Open

JDeepD wants to merge 1 commit into
WordPress:trunkfrom
JDeepD:fix/54378-quick-edit-parent-dropdown

Conversation

@JDeepD

@JDeepD JDeepD commented Nov 5, 2026

Copy link
Copy Markdown

The Quick Edit and Bulk Edit parent drop-down on the Pages screen calls get_pages(), which runs SELECT wp_posts.* for every published page on every load of the screen. The drop-down only needs a few fields, but the query also loads post_content and the other long text columns. On sites with many or large pages this is slow and uses a lot of memory.

WP_Query has no way to select specific columns, so this PR adds one and uses it for the drop-down.

Changes

  • WP_Query: the fields argument now also accepts an array of post field names.
    • Only those fields and ID are selected. Unknown names are ignored, so arbitrary input never reaches the SQL.
    • The result is an array of partial WP_Post objects. Fields that weren't selected are empty.
    • Partial objects are not added to the post cache. The query cache already skips non-standard field sets.
    • The loop still sets up full posts: the_post() already loads the full post whenever fields isn't 'all'.
  • get_pages(): new optional fields argument, passed to WP_Query. post_parent, post_type and post_status are always loaded, so hierarchy and functions like get_permalink() keep working. It isn't added to the defaults, so the parsed arguments are unchanged for existing callers.
  • wp_dropdown_pages(): adds its value_field to fields when fields is given.
  • Quick Edit parent drop-down: loads every field except post_content, post_excerpt, post_content_filtered, to_ping and pinged.

Code that doesn't pass fields as an array behaves exactly as before, including caching.

Performance

The drop-down query itself:

Pages × content Trunk (1 × SELECT *) Current Changeset Data returned
500 × 10 KB 4.5 ms 2.5 ms 5.24 MB → 0.30 MB
2,000 × 10 KB 20.6 ms 10.0 ms 20.97 MB → 1.22 MB
5,000 × 10 KB 47.8 ms 23.5 ms 52.43 MB → 3.05 MB
2,000 × 50 KB 81.2 ms 8.7 ms 99.11 MB → 1.22 MB

WP_Posts_List_Table::inline_edit():

Pages Peak memory Pages written to the post cache
500 15.1 MB → 3.1 MB 400 → 0
2,000 60.4 MB → 7.0 MB 1,600 → 0
5,000 151.3 MB → 14.8 MB 4,000 → 0

The drop-down HTML is identical to trunk at every size. Total inline_edit() time is about the same, since building the <option> markup dominates.

In the Quick Edit and Bulk Edit parent drop-down only, get_pages / list_pages callbacks receive WP_Post objects with empty post_content, post_excerpt, post_content_filtered, to_ping and pinged. Plugins that need them can remove fields via the quick_edit_dropdown_pages_args filter.

Trac ticket: https://core.trac.wordpress.org/ticket/54378

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5
Used for: Reproducing the issue, drafting the patch and tests. I reviewed, tested and edited the final implementation, tests and benchmarks.


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

The Quick Edit and Bulk Edit parent drop-down on the Pages screen
selected every column of every published page, including post_content,
on every load of the screen. On sites with many or large pages this made
the query slow and used a lot of memory.

The `fields` argument of WP_Query now accepts an array of post field
names. Only those fields and ID are selected. Unknown names are ignored.
The partial post objects are not added to the post cache, and the loop
still sets up full posts.

get_pages() gains a `fields` argument that is passed to WP_Query, with
post_parent, post_type and post_status always loaded. wp_dropdown_pages()
also loads its `value_field`. The Quick Edit parent drop-down now loads
every field except the long text columns.
@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs.

Core Committers: Use this line as a base for the props when committing in SVN:

Props jdeep.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.


Props Bot commands

You can trigger Props Bot actions by commenting on this PR:

  • @propsbot add <username> to give props to a GitHub user. Requires write access.
  • @propsbot remove <username> to leave a user out of the props. Requires write access.
  • @propsbot refresh to refresh this list. Adding the props-bot label works too.

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant