3

I'm trying to write a loop that excludes posts that don't have attachments in their content areas.

I've got 200 posts in a custom post type called "students". I need to do a query of all students with a gallery or attachment in their content area. NOT their featured image.

Can this be done? This is whats going on with my loop so far. Not working at all, I'm guessing that $gotimages isn't outputting posts with attachments...


**FINAL EDIT: The loop here works perfectly, the issue that I've found is that you can only assign images once. Which means, if you upload images to a post, then reuse the same images for another post, only the first post image will show. This loop works by association to the post.

Re-upload your images for every post to make this work and have unique images.**

EDIT: Using the loop from s_ha_dum♦, this is getting closer to the thing I'm looking for, though it's only pulling one result in the loop.

<?php
$args = array( 
  'post_type'      => 'attachment',
  'post_mime_type' => 'image',
  'post_status' => 'inherit',
  'posts_per_page' => -1,
  'post_parent__not_in' => array(0),
  'meta_query' => array(
    array(
      'key' => '_thumbnail_id',
      'value' => 'x',
      'compare' => 'NOT EXISTS'
    )
  ),
  'fields' => 'post_parent'
);
$atts = new WP_Query($args);

$parents = array_unique(wp_list_pluck($atts->posts,'post_parent'));

//var_dump($parents);

// get your students posts
$args = array( 
    'post_type' => 'student',
    'post__in' => $parents
);
$students = new WP_Query($args);

// lets see some results
//var_dump($students->request);
//var_dump($students->posts);

echo '<hr />';

// Looping through the students
// I need to pull a random image from the post' gallery / attachements
// Unsure of how I do this
if ( $students->have_posts() ) {
    while ( $students->have_posts() ) {
        $students->the_post();

        echo get_the_title();
        echo '<hr />';
    }
} else {
    // no posts found
    echo 'No students exist';
}
/* Restore original Post Data */
wp_reset_postdata();

?>

2
  • Do not use query_posts. Rather use WP_Query. Rewrite your code and repost your new code. Commented May 11, 2014 at 18:21
  • @PieterGoosen updated to reflect an answer, that isn't correct, but is closer Commented May 12, 2014 at 11:20

1 Answer 1

2

First, please don't use query_posts() (emphasis mine)!

Note: This function isn't meant to be used by plugins or themes. As explained later, there are better, more performant options to alter the main query. query_posts() is overly simplistic and problematic way to modify main query of a page by replacing it with new instance of the query. It is inefficient (re-runs SQL queries) and will outright fail in some circumstances (especially often when dealing with posts pagination). Any modern WP code should use more reliable methods, like making use of pre_get_posts hook, for this purpose.

http://codex.wordpress.org/Function_Reference/query_posts

Second, this isn't going to work:

$gotimages = get_children( array(
  'post_type'      => 'attachment',
  'post_mime_type' => 'image',
  'post_parent'    => get_the_ID()
)),

array(
  'key' => implode(', ', $gotimages),
  'compare' => '='
),

This line...

 'post_parent'    => get_the_ID()

... is probably going to be a problem as it will return the current post ID in the Loop, but your Loop doesn't start until later. Given how your code is written I think you are trying to construct a kind of sub-query, but it doesn't work like that.

This line ...

'key' => implode(', ', $gotimages),

... will definitely be a problem. $gotimages, if it has results, is going to be an array of objects. When you try to implode that you will get something like:

Catchable fatal error: Object of class WP_Post could not be converted to string...

Try it with a post ID know to have attachments:

$gotimages = get_children( array(
    'post_type'      => 'attachment',
    'post_mime_type' => 'image',
    'post_parent'    => 1
));
var_dump(implode(', ', $gotimages));

And additionally, I am fairly sure that the key argument of a meta_query does not take a comma delimited string even if that object were to implode() correctly.

Third, get_children() is going to return all attachments, one of which is the featured image, but, additionally, WordPress handles attachments badly and once an image is attached to a post it is hard to unattach it. You will get images that where once displayed in the post body but are no longer displayed. So, logically, even if all of the code worked, what you are attempting won't work.

In fact, what you are trying to do is tricky and labor intensive as it is going to require a regex on the post body to search for images. If you have galleries involved it become more complicated still.

So, how close can I get you?

I need to do a query of all students with a gallery or attachment in their content area. NOT their featured image.

This, if I've done it right, should get you close to "all students with a gallery or attachment in their content area":

$args = array( 
  'post_type'      => 'attachment',
  'post_mime_type' => 'image',
  'post_status' => 'inherit',
  'posts_per_page' => -1,
  'post_parent__not_in' => array(0),
  'meta_query' => array(
    array(
      'key' => '_thumbnail_id',
      'value' => 'x',
      'compare' => 'NOT EXISTS'
    )
  ),
  'fields' => 'post_parent'
);
$atts = new WP_Query($args);

$parents = array_unique(wp_list_pluck($atts->posts,'post_parent'));

// get your students posts
$args = array( 
  'post_type' => 'students',
  'post__in' => $parents
);
$students = new WP_Query($args);

// see some results
var_dump($students->request);
var_dump($students->posts);

What it doesn't do is:

  • Compensate for cases where images where attached and then deleted from the post body. Those will still show up.
  • And cases where images where manually written into the post body. Those will not show up.

Your other option would be to search your post type for some plausibly identifiable string:

$args = array( 
  'post_type' => 'students',
  's' => '<img '
);
$students = new WP_Query($args);

I am not sure how robust that will be but it does return some reasonable results when I try it.

9
  • Such an in-depth answer, I really appreciate this, however, the loop only shows 1 result. No matter how many posts there are. Commented May 12, 2014 at 11:02
  • Using $students->the_post(); I can't only get one result back. I don't know if I'm missing something here Commented May 12, 2014 at 11:10
  • Updated the question to reflect your loop, hoping it helps find a solution Commented May 12, 2014 at 11:20
  • I thought through this pretty carefully. If you are not getting the results you expect I think the problem is with what you are querying for and not with the query itself, but if you can identify what should be returned that isn't that would help.
    – s_ha_dum
    Commented May 12, 2014 at 13:49
  • I'm trying to get a list of all the students that have uploaded images to their content area. Then in this loop, show 1 random image from each student's post (the_content). Commented May 12, 2014 at 15:05

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.