Skip to content

Commit c3563e6

Browse files
committed
Keep the object cache when listing computed post fields
Fields like post meta are read through WP_Post::__get(), which uses the object cache. When the first post lacks such a field, the formatter can't stream and only reads the fields once all posts are loaded. By then the cache was cleared after each chunk, so every post needed another query, which made `wp post list --fields=ID,<meta key>` slower than before. Only clear the cache when all displayed fields are plain post properties. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D26yjkN2BiqCXT6p6o1WqS
1 parent f78534d commit c3563e6

2 files changed

Lines changed: 41 additions & 5 deletions

File tree

‎features/post.feature‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,3 +1173,25 @@ Feature: Manage WordPress posts
11731173

11741174
When I run `wp post list --post_status=publish --orderby=ID --order=desc --posts_per_page=2 --fields=ID,url --format=csv`
11751175
Then STDOUT should match /^ID,url\n(\d+),https?:\/\/example\.com\/\?p=\1\n(\d+),https?:\/\/example\.com\/\?p=\2$/
1176+
1177+
Scenario: List post meta as a field for some posts only
1178+
Given a WP install
1179+
And I run `wp post create --post_title=First --post_status=publish --porcelain`
1180+
And save STDOUT as {FIRST}
1181+
And I run `wp post create --post_title=Second --post_status=publish --porcelain`
1182+
And save STDOUT as {SECOND}
1183+
And I run `wp post meta add {SECOND} batch_meta second-value`
1184+
1185+
When I run `wp post list --post__in={FIRST},{SECOND} --orderby=ID --order=asc --fields=ID,batch_meta --format=csv`
1186+
Then STDOUT should be:
1187+
"""
1188+
ID,batch_meta
1189+
{FIRST},
1190+
{SECOND},second-value
1191+
"""
1192+
1193+
When I try `wp post list --post__in={FIRST},{SECOND} --fields=ID,missing_meta --format=csv`
1194+
Then STDERR should be:
1195+
"""
1196+
Warning: Field not found in any item: missing_meta.
1197+
"""

‎src/Post_Command.php‎

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,8 +1062,8 @@ public function list_( $args, $assoc_args ) {
10621062
$query = new WP_Query( $query_args );
10631063
$formatter->display_items( $query->posts ?? [] );
10641064
} else {
1065-
$need_url = 'url' === $formatter->field || in_array( 'url', (array) $formatter->fields, true );
1066-
$formatter->display_items( $this->query_posts_in_chunks( $query_args, $need_url ) );
1065+
$fields = $formatter->field ? [ $formatter->field ] : (array) $formatter->fields;
1066+
$formatter->display_items( $this->query_posts_in_chunks( $query_args, $fields ) );
10671067
}
10681068
}
10691069

@@ -1074,11 +1074,23 @@ public function list_( $args, $assoc_args ) {
10741074
* at a time with the same query arguments, and the object cache is cleared after each
10751075
* chunk. Formats that can be written item by item are then streamed by the formatter.
10761076
*
1077+
* Fields that WP_Post computes on access, like post meta, are read from the object
1078+
* cache. If any of them are displayed, the cache is kept, because the formatter may
1079+
* only read them once all posts have been loaded.
1080+
*
10771081
* @param array<string, mixed> $query_args WP_Query arguments.
1078-
* @param bool $need_url Whether to add the `url` property to each post.
1082+
* @param string[] $fields Fields that will be displayed.
10791083
* @return \Generator<int, \WP_Post>
10801084
*/
1081-
private function query_posts_in_chunks( $query_args, $need_url ) {
1085+
private function query_posts_in_chunks( $query_args, $fields ) {
1086+
$need_url = in_array( 'url', $fields, true );
1087+
$clear_cache = true;
1088+
foreach ( $fields as $field ) {
1089+
if ( 'url' !== $field && ! property_exists( 'WP_Post', $field ) && ! property_exists( 'WP_Post', 'post_' . $field ) ) {
1090+
$clear_cache = false;
1091+
}
1092+
}
1093+
10821094
/** @var int[] $ids */
10831095
$ids = ( new WP_Query( array_merge( $query_args, [ 'fields' => 'ids' ] ) ) )->posts;
10841096

@@ -1117,7 +1129,9 @@ private function query_posts_in_chunks( $query_args, $need_url ) {
11171129
}
11181130

11191131
unset( $posts, $query );
1120-
self::clear_runtime_object_cache();
1132+
if ( $clear_cache ) {
1133+
self::clear_runtime_object_cache();
1134+
}
11211135
}
11221136
}
11231137

0 commit comments

Comments
 (0)