I'm making a widget that shows a set of images from recent custom posts. I want to run the following query:

FROM wp_posts p
WHERE post_type='attachment'
AND post_mime_type LIKE 'image%'
AND post_parent IN (
  FROM wp_posts
  WHERE post_type ='my_custom_post_type'
ORDER BY post_date DESC

and receive an array of attachment objects. I am unclear on the canonical WordPress method for doing something like this. Where should I start?

4 Answers 4


It seems like a bit of a waste to run through two loops just to use some built in API functions that weren't designed for a use case like this.

I think you're better off to use your SQL combined with the wpdb class -- faster and cleaner.

Example (with modified SQL):

function wpse52315_get_attach()
    global $wpdb;
    $res = $wpdb->get_results("select p1.*
        FROM {$wpdb->posts} p1, {$wpdb->posts} p2
        WHERE p1.post_parent = p2.ID 
           AND p1.post_mime_type LIKE 'image%'
           AND p2.post_type = 'your_cpt'
        ORDER BY p2.post_date
        LIMIT 10;"
    return $res;
  • thanks for this. I thought this might be the direction to go, but WP seems to discourage direct "touching" and I didn't want to set myself up for unfortunate side effects.
    – dnagirl
    Commented May 16, 2012 at 17:39

What I recommend is one instance of WP_Query for looping through all the custom post type post and then get_posts() to retrieve the attachments for each post. Here's an untested code snippet that should do what you want:

// Setup array for storing objects
$my_attachment_objects = array();

// Arguments for custom WP_Query loop
$my_cpts_args = array(
    'post_type' => 'my_custom_post_type',
    'posts_per_page' => 10

// Make the new instance of the WP_Query class
$my_cpts = new WP_Query( $my_cpts_args );

// And Loop!
if( $my_cpts->have_posts() ) : while( $my_cpts->have_posts() ) : $my_cpts->the_post();

    // arguments for get_posts
    $attachment_args = array(
        'post_type' => 'attachment',
        'post_mime_type' => 'image',
        'post_status' => null, // attachments don't have statuses
        'post_parent' => $post->ID
    // get the posts
    $this_posts_attachments = get_posts( $attachment_args );
    // append those posts onto the array
    $my_attachment_objects[$post->ID] = $this_posts_attachments; // make an array with the post_id as the key, just in case that's useful

endwhile; endif; wp_reset_postdata();

Hope this helps.

  • This was exactly what I needed. Took me hours searching. Tnx buddy!
    – XVirtusX
    Commented May 23, 2019 at 13:07

Maybe something like this:

  $args = array( 'post_type' => 'portfolio', 'posts_per_page' => 10 );
  $loop = new WP_Query( array ( 'orderby' => 'title', 'order' => 'DESC' ) );  
  while ( $loop->have_posts() ) : $loop->the_post();
    echo '<div class="entry-content">'; the_content();
    echo '</div>';

If all you're interested in is the number of attachments for a particular post type, you can modify Chris' function slightly to the following:

function myprefix_image_count() {
    global $wpdb;
    $res = $wpdb->get_var("select COUNT(*)
        FROM {$wpdb->posts} p1, {$wpdb->posts} p2
        WHERE p1.post_parent = p2.ID
           AND p1.post_mime_type LIKE 'image%'
           AND p2.post_type = 'your_cpt_name'
        ORDER BY p2.post_date;"
    $imageCount = (int)$res;
    return $imageCount;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.