get attachments for all posts of particular post type

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

SELECT p.* 
FROM wp_posts p
WHERE post_type='attachment'
AND post_mime_type LIKE 'image%'
AND post_parent IN (
  SELECT ID
  FROM wp_posts
  WHERE post_type ='my_custom_post_type'
)
ORDER BY post_date DESC
LIMIT 10;

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

Related posts

Leave a Reply

4 comments

  1. 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):

    <?php
    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;
    }
    
  2. 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.

  3. Maybe something like this:

    <?php
      $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();
        the_title();
        echo '<div class="entry-content">'; the_content();
        echo '</div>';
      endwhile;
      ?>
    
  4. 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:

    <?php
    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;
    }
    ?>