• What I’m trying to do is generate a loop that only displays posts with image attachments. I’m able to hide posts without attachments but they’re still counted in the loop, so if I have 5 posts and 1 does not have an attachment only 4 posts are displayed. I want to always be able to display 5 posts, so the next post to have an attachment becomes post number 5.

    This is the code I am using:

    <?php
    query_posts('posts_per_page=5&meta_key=slider&meta_value=Include'); if (have_posts()) : while (have_posts()) : the_post(); ?>
    <?php
    $args = array(
    'post_type' => 'attachment',
    'numberposts' => 1,
    'post_status' => null,
    'post_mime_type' => 'image',
    'orderby' => menu_order,
    'order' => ASC,
    'post_parent' => $post->ID
    );
    $attachments = get_posts($args);
    if ($attachments) {
    foreach ($attachments as $attachment) {
    ?>
    <div>
    	<span class="slider-text">
    		<h3><a href="<?php the_permalink(); ?>" rel="bookmark" title="<?php the_title(); ?>"><?php echo slidertitle(get_the_title());?></a></h3>
    	</span>
    	<div class="slider-image">
    		<img src="<?php echo wp_get_attachment_url($attachment->ID); ?>" alt="" />
    	</div>
    </div>
    <?php } ?>
    <?php endwhile; endif; wp_reset_query(); ?>

    I would like to able to add a post_type=attachment criteria to query_posts but this does not work.

Viewing 12 replies - 1 through 12 (of 12 total)
  • Use below code after $attachments = get_posts($args);.

    if(count($attachments) > 0) :
    foreach($attachments as $attachment) : ?>
    <div>
      <span class="slider-text">
      <h3><a href="<?php the_permalink(); ?>" rel="bookmark" title="<?php the_title(); ?>"><?php echo slidertitle(get_the_title());?></a></h3>
      </span>
      <div class="slider-image">
        <img src="<?php echo wp_get_attachment_url($attachment->ID); ?>" alt="" />
      </div>
    </div>
    <?php endforeach; else : ?>
    <div>
      <span class="slider-text">
      <h3><a href="<?php the_permalink(); ?>" rel="bookmark" title="<?php the_title(); ?>"><?php echo slidertitle(get_the_title());?></a></h3>
      </span>
    </div>
    <?php endif; endwhile; endif; wp_reset_query(); ?>
    Thread Starter GhostPool

    (@ghostpool)

    Hi kz,

    The problem with this code is that it still loads the posts without attachments into the loop as you’ve used the else condition. Even removing the else condition and simply using if(count($attachments) > 0) still counts the posts without attachments in the loop. I think they need to be excluded in the query_posts loop before even reaching the get_posts query.

    <?php
    global $wpdb;
    $posts = $wpdb->get_results
    ("
      SELECT *
      FROM $wpdb->posts
      WHERE
          post_status = 'publish'
        AND
          ID IN (
    	SELECT DISTINCT post_parent
    	FROM $wpdb->posts
    	WHERE
    	  post_parent > 0
    	AND
    	  post_type = 'attachment'
    	AND
    	  post_mime_type IN ('image/jpeg', 'image/png')
          )
        ORDER BY post_date DESC
    ");
    
    foreach($posts as $post) :
      setup_postdata($post);
    ?>
    <div>
      <span class="slider-text">
        <h3><a href="<?php the_permalink(); ?>" rel="bookmark" title="<?php the_title(); ?>"><?php echo slidertitle(get_the_title());?></a></h3>
      </span>
      <div class="slider-image">
        <img src="<?php echo wp_get_attachment_url($attachment->ID); ?>" alt="" />
      </div>
    </div>
    <?php
    endforeach;
    wp_reset_query();
    ?>

    Pointing to a somewhat related hackers discussion:
    http://lists.automattic.com/pipermail/wp-hackers/2010-January/029995.html

    Thread Starter GhostPool

    (@ghostpool)

    kz,

    This looks really promising, it skips the posts with no images as I wanted.

    Few issues though:

    1) I can’t seem to get the images to display. The image URLs are being generated by <?php echo wp_get_attachment_url($attachment->ID); ?>.

    2) How do I integrate a meta_value/meta_key filter?

    3) Sticky posts no longer seem to show at the top of the loop.

    Thread Starter GhostPool

    (@ghostpool)

    Right, I’ve sorted issue 2), I’m still working on 1) and 3) though. πŸ™‚

    1)Use
    <?php echo wp_get_attachment_image($attachment->ID); ?>
    or
    <img src="<?php echo wp_get_attachment_image_src()($attachment->ID); ?>" alt="" />
    instead of
    <img src="<?php echo wp_get_attachment_url($attachment->ID); ?>" alt="" />

    3)Prepend sticky only loop.

    $sticky=get_option('sticky_posts');
    query_posts('p=' . $sticky[0]);
    /* do stuff */
    wp_reset_query();

    Thread Starter GhostPool

    (@ghostpool)

    Thanks for all the help kz.

    Unfortunately neither of those alternatives display the images. I don’t think the $attachment->ID is being parsed. Does the post ID need to be called somewhere – so it knows what attachment IDs to pull?

    Where would I insert this relative to the other code? Does this only show sticky posts, because I want to show sticky posts at the top and then normal posts below just like in the main loop on the index page.

    $sticky=get_option('sticky_posts');
    query_posts('p=' . $sticky[0]);
    /* do stuff */
    wp_reset_query();
    <?php
    // sticky section
    $sticky=get_option('sticky_posts');
    query_posts('p=' . $sticky[0]);
      /* do stuff */
    wp_reset_query();
    // main section
    global $wpdb;
    $posts = $wpdb->get_results
    ("
      SELECT *
      FROM $wpdb->posts
      WHERE
        post_status = 'publish'
        AND
          ID IN (
    	SELECT DISTINCT post_parent
    	FROM $wpdb->posts
    	WHERE
    	  post_parent > 0
    	AND
    	  post_type = 'attachment'
    	AND
    	  post_mime_type IN ('image/jpeg', 'image/png')
          )
        ORDER BY post_date DESC
    ");
    
    foreach($posts as $post) :
      setup_postdata($post);
    ?>
    <div>
      <span class="slider-text">
        <h3><a href="<?php the_permalink(); ?>" rel="bookmark" title="<?php the_title(); ?>"><?php echo slidertitle(get_the_title());?></a></h3>
      </span>
      <div class="slider-image">
        <?php
        $images = get_children(array(
          'post_parent' => get_the_id(),
          'post_type' => 'attachment',
          'post_mime_type' => 'image',
          'orderby' => 'ID',
          'order' => 'ASC'
        ));
        $ids = array_keys($images);
        echo wp_get_attachment_image($ids[0]);
        ?>
      </div>
    </div>
    <?php
    endforeach;
    wp_reset_query();
    ?>
    Thread Starter GhostPool

    (@ghostpool)

    Great stuff, the images are now working.

    With the sticky posts I need them to be part of the same loop because I only want a maximum of 4 posts displayed and I’m calling the loop in a slider.

    Thanks for posting all of this GhostPool & Kz.
    I have been searching for this for a few days and I got it to work. So I figure I will recount my experience so that it may be searchable for others like me.

    I was trying to use the code at this link to attempt to exclude posts based on a similar set of requirements as GhostPool.

    That did not work and was a bit bulky in retrospect. I then tried to build a filter that would alter the query in a similar manner as what is described above. That is: excluding posts based whether the image attachment was available and if not skipping it while maintaining the same number in my post count. It didn’t turn out too well…

    I found this via a google search for ‘excluding posts without attachments’. This code works! Thank you!

    If people are having trouble figuring out where the wpdb… is supposed to go (because it doesn’t look like the common if,while statements), here is a resource that helped me out a lot.

    NOTE: for further control over the # of posts displayed add ‘ LIMIT #; ‘ after ‘ ORDER BY post_date DESC ‘

    Cheers.

Viewing 12 replies - 1 through 12 (of 12 total)
  • The topic ‘Exclude Posts Without Attachments From Query’ is closed to new replies.