Modifying WP_Query output everywhere is repetitive. the_posts filter catches all query results in one place.
Add to functions.php:
add_filter('the_posts', function($posts, $query) {
// Don't modify admin queries
if (is_admin()) return $posts;
// Example: Add reading time to all posts
foreach ($posts as $post) {
$word_count = str_word_count(strip_tags($post->post_content));
$reading_time = ceil($word_count / 200);
$post->reading_time = $reading_time . ' min read';
}
return $posts;
}, 10, 2);
// Use in templates
reading_time; ?>
Other Use Cases:
// Add view count from separate table
foreach ($posts as $post) {
$post->view_count = get_view_count($post->ID);
}
// Inject ads every 3rd post
$posts_with_ads = [];
foreach ($posts as $i => $post) {
$posts_with_ads[] = $post;
if (($i + 1) % 3 === 0) {
$ad = create_ad_post_object();
$posts_with_ads[] = $ad;
}
}
return $posts_with_ads;
