I am working on a shortcode that will create and grid of all custom posts of a certain type. This is working all well, if I get only the post titles. However, if I add the post thumbnails, I move from making about 28 queries to about 1000 queries.
When looking at the queries through Query Monitor I can see that the call to get_the_post_thumbnail( $post->ID, 'medium' )
is duplicated 328 times. Plus it calls wp_attachment_is()
, wp_get_attachment_url()
and wp_get_attachment_metadata()
This is the important part of the code
$args = array(
'post_type' => 'zxy_movie',
'post_status' => 'publish',
'orderby' => 'post_title',
'order' => 'ASC',
'posts_per_page' => - 1,
);
$posts = get_posts( $args ); // 332
$output = '';
if ( $posts && count( $posts ) > 0 ) {
foreach ( $posts as $post ) {
$output .= '<div class="zxy-item">';
$output .= '<a href="' . get_permalink( $post->ID ) . '">';
$output .= '<div class="zxy-image">';
$output .= get_the_post_thumbnail( $post->ID, 'medium' );
$output .= '</div>';
$output .= '<div class="zxy-title">';
$output .= $post->post_title;
$output .= '</div>';
$output .= '</a>';
$output .= '</div>';
}
}
return $output;
So can anyone here provide me with any tip, tricks, ideas and/or solutions to reduce the number of queries needed to get the post thumbnail image.
I am working on a shortcode that will create and grid of all custom posts of a certain type. This is working all well, if I get only the post titles. However, if I add the post thumbnails, I move from making about 28 queries to about 1000 queries.
When looking at the queries through Query Monitor I can see that the call to get_the_post_thumbnail( $post->ID, 'medium' )
is duplicated 328 times. Plus it calls wp_attachment_is()
, wp_get_attachment_url()
and wp_get_attachment_metadata()
This is the important part of the code
$args = array(
'post_type' => 'zxy_movie',
'post_status' => 'publish',
'orderby' => 'post_title',
'order' => 'ASC',
'posts_per_page' => - 1,
);
$posts = get_posts( $args ); // 332
$output = '';
if ( $posts && count( $posts ) > 0 ) {
foreach ( $posts as $post ) {
$output .= '<div class="zxy-item">';
$output .= '<a href="' . get_permalink( $post->ID ) . '">';
$output .= '<div class="zxy-image">';
$output .= get_the_post_thumbnail( $post->ID, 'medium' );
$output .= '</div>';
$output .= '<div class="zxy-title">';
$output .= $post->post_title;
$output .= '</div>';
$output .= '</a>';
$output .= '</div>';
}
}
return $output;
So can anyone here provide me with any tip, tricks, ideas and/or solutions to reduce the number of queries needed to get the post thumbnail image.
In answering my own question I have decide to go the pure SQL query route as WP runs too many queries in fetching a post and its attached post thumbnail, in addition to fetching and building meta for that thumbnail.
Here is the code I ended up with:
$query2 = "SELECT post.ID, post.post_title, thumbnail_url.meta_value as thumbnail_url
FROM $wpdb->posts as post
LEFT OUTER JOIN $wpdb->postmeta as thumbnail
ON post.ID = thumbnail.post_id AND thumbnail.meta_key = '_thumbnail_id'
LEFT OUTER JOIN $wpdb->postmeta as thumbnail_url
ON thumbnail.meta_value = thumbnail_url.post_id
AND thumbnail_url.meta_key = '_wp_attached_file'
WHERE 1 = 1
AND post.post_type = 'zxy_movie'
AND post.post_status = 'publish'
ORDER BY post.post_title ASC";
$posts = $wpdb->get_results( $query2, OBJECT );
Please note: This is still and expensive query and I do not recommend it on large sites.
get_the_post_thumbnail()
requires a query to the database to get the ID of the attachment, and then another query or two to get all the information about that attachment, including the URL, dimensions, alt text etc. It's a lot of information to output onto a page, so it takes a fair bit to query it all, especially given WordPress' db structure. – Jacob Peattie Commented Jan 23, 2019 at 14:10'order'=> 'ASC',
and leaving it as the default ofDESC
but reversing your loop using php. You might need to increase the number of posts queried to 1000+ to see any difference though. (you would use a for ($i in) loop rather than a foreach to reverse the output order) – admcfajn Commented Jan 23, 2019 at 23:15