Programmatically Pull Attachments from WordPress Posts

One of my favorite tricks in using WordPress as a CMS is to have it handle photo resizing and insertion into pages automatically. For example, swissmiss and I just launched Convert (a NYC based Green Roof Service) today. Within the projects section they display photos of the green roofing projects they’ve done and let you download a project sheet PDF.

It would be quite a burden for the client to have to know how to create all of the appropriate image sizes, upload the photos and insert the correct HTML tags. So here’s what we’ve done instead:

First, we set the WordPress image sizes to match the thumbnail and large sizes that we needed by going to Settings->Media in the admin tool.

Next, the client just has to upload all of their photos and a PDF for the project sheet. The images are automatically scaled by WordPress and attached to the page. They can also change the order the photos appear by dragging/dropping them in the admin tool.

Finally, adding this simple snippet of code to the functions.php in their theme, I can ask for all of the images associated with the post.

// get all of the images attached to the current post
function aldenta_get_images($size = 'thumbnail') {
	global $post;
	
	$photos = get_children( array('post_parent' => $post->ID, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID') );
	
	$results = array();

	if ($photos) {
		foreach ($photos as $photo) {
			// get the correct image html for the selected size
			$results[] = wp_get_attachment_image($photo->ID, $size);
		}
	}

	return $results;
}

So, if you want all of the thumbnail images (as an array of html tags) you can make the default call:

$photos = aldenta_get_images();

If you want all of the medium sized images you pass medium as the size:

$photos = aldenta_get_images('medium');

My function has a bit more going on inside of it but you get the idea of what you can do with this. Another way I like to use it is to pull the first image from the post. Sometimes, you want to display a thumbnail image that represents a post. Here’s how I like to do that:

// get the first image attached to the current post
function aldenta_get_post_image($size = 'thumbnail') {
	global $post;

	$photos = get_children( array('post_parent' => $post->ID, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID') );
	
	if ($photos) {
		$photo = array_shift($photos);
		return wp_get_attachment_image($photo->ID, $size);
	}
	
	return false;
}

// the html tag for the first image or false if no image is found
$photo = aldenta_get_post_image();

What if you want to get the PDF attached to the post? No problem – it works the same but you change the mime type to application/pdf.

// get the first PDF attached to the current post
function aldenta_get_post_pdf() {
	global $post;

	$attachments = get_children( array('post_parent' => $post->ID, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'application/pdf', 'order' => 'ASC', 'orderby' => 'menu_order ID') );
	
	if ($attachments) { 
		$attachment = array_shift($attachments);
		return wp_get_attachment_url($attachment->ID);
	}
	
	return false;
}

// the url to the first pdf or false if no pdf is found
$pdf = aldenta_get_post_pdf();

This technique has helped me tremendously and I hope it does the same for you.

46 Responses

  1. Great technique, this is the sort of thing that makes me wonder why I put up with the current image/file handling in Expression Engine.

    Thanks for sharing!

  2. Awesome! Thx for showing me how to do this…this a great technique I’ll be using more.

  3. Great tip. Keep sharing you knowledge, my friend.

  4. Questions:
    . How do you remove the images from your content( )?
    . Are you using custom fields for project informations?

  5. @Eliseu, when using this method, the images are never added to the page content so there is no need to remove them. Yes, I’m using custom fields for project information but I also create a custom interface in WordPress so the client doesn’t have to use the clunky custom fields boxes. They click on Add Project instead of Add Page and it shows them the exact fields they need to key in. I’ll probably talk more about how to do that in a future post.

  6. Could you help me, as this seems perfect… I want a conditional so that IF a post from a specific category has an image attached THEN xyz happens ELSE nothing

    Thanks heaps

  7. Question :
    The Following Function:
    function aldenta_get_post_image($size = ‘thumbnail’)
    to get the first thumbnail of the post attachment returns empty square boxes instead of the thumbnail when i call the function
    This is how i am calling the function in my template file:
    <img src=”"

    i am trying to call the thumnail along with the post title.

  8. Sorry the funtion call didnt get listed properly , below is how i m calling the function.
    <img src=echo $photo = aldenta_get_post_image()

  9. Hey John. This is a great plugin/function. Thanks for sharing.

    I slightly modified the first two lines of code, and now you can pass in an instance of a post object to the function.

    function aldenta_get_post_image($size = ‘thumbnail’, $post = null) {
    if($post == null){ global $post; }
    ….

    Useful if you’re doing custom selects, and/or working with WP data objects in php.

  10. example usage for the modification:

    $query = ‘your custom wp query’;
    $custom_select = $wpdb->get_results($query);
    $photo = aldenta_get_post_image(‘large’, $custom_select[0]);

  11. Thank you. This is the most elegant solution that I have come across. Again, thank you. I just wish I had found this earlier.

  12. I wanted to know if you and swissmiss created the entire site out of wordpress, so you basically created your own theme?

  13. What about pulling only the text?

  14. This works great.

    Would you have any idea how to make this into a conditional? to say, if there is an attachement – output the link to a PDF, but if there is no attachement, do nothing?

    Many Thanks

  15. I think I’m missing something here. All I need to do is add $photos = aldenta_get_images(‘full’); between some php tages within my page loop (I assume it works with pages as well as posts?)

    I get nothing on my page. Frustrating.

  16. @Pete, I’m not sure exactly what you’re trying to do. You can check which category you’re in (Conditional_Tags @ WordPress Codex) and only print the link if needed.

    @Matt, yeah you’re right. This was just one example and use similar techniques depending on the needs of the website.

    @Rebecca, yes the swissmiss site is a custom WordPress theme.

    @fx, I’m not sure what you mean about pulling back text but you can get the photo title, caption and description by printing out the variables of the attachment. You’d have to change the examples above to not return just the url.

    @dave, I typically do something like this. It will only print the link if a PDF exists.

    if ($pdf = aldenta_get_post_pdf()) {
    	echo '<a href="' . $pdf . '">My PDF</a>';
    }
    

    @Edward, that call will give you an array of images attached to the current page or post. You need to print them out to the screen. Here’s one way to print each image:

    $photos = aldenta_get_images('full');
    
    if ($photos) {
    	foreach ($photos as $photo) {
    		echo "$photo<br />";
    	}
    }
    
  17. John, thank you very much. I know a little PHP and if I’d studied the code carefully I’d have realised that I needed to actually take he output from your function. But I don’t know enough to do that. Your a life saver.
    Thanks and regards, Edward

  18. Is it possible to access other properties of the attachment? For example, the Title, Link URL etc. I’m trying to create a gallery for a client. I know I could use custom fields but I’m trying to let my client use the user interface that exists for attaching images to a page or post rather than rely on them copying a url into a custom field.
    Regards, Edward

  19. @Edward, yes you can access all of the information stored in the attachment. In the functions above, you’d need to return the attachment object(s) instead of calling wp_get_attachment_image() which creates the html image code for you. Here’s an example:

    function aldenta_get_images($size = 'thumbnail') {
    	global $post;
    
    	return get_children( array('post_parent' => $post->ID, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID') );
    }
    
    if ($images = aldenta_get_images()) {
    	foreach ($images as $image) {
    		echo $image->post_title;   // title
    		echo $image->post_content; // description
    		echo $image->post_excerpt; // caption
    	}
    }
    
  20. Great John. Thanks. Using the snippet above I can get the title etc that I asked about but how do I now pull up the thumbnail and url as well that was in the original code? I said I didn’t know too much php :-) Does $image have an $image->image attribute?
    Regards, Edward

  21. It’s returning an error like “Fatal error call to function aldenta_get_attachment_image”. I’m not good with PHP, even so, I cant figure out what i’m doing wrong since I copied and pasted the code right into functions.php…

  22. @Edward, if you want the thumbnail image or url you can use:

    echo wp_get_attachment_image($image->ID, 'thumbnail'); // thumbnail image
    echo wp_get_attachment_url($image->ID); // attachment url
    

    @Emanoel, I made a mistake updating the post and accidentally replaced wp_get_attachment with aldenta_get_attachment. If you copy and paste the updated post code with wp_get_attachment_image it should work. There is no function called aldenta_get_attachment_image.

  23. This is a pretty neat technique ;) I’ve been playing around with something pretty close to it myself.

    Have you ever used a similar setup where the images linked to external sites rather than to the image itself?

  24. @patrick, in cases like that I typically have the client enter the url into the Description field when they upload the image. Then, I use the description to build the link around image.

  25. Ha, that’s exactly what I ended up doing ;)

    It’s a bit frustrating that you can’t enter in external links for the Link URL field. I suppose one could add a field to the wp-posts table and store it there, but it seems like WP would have a built in way of doing something that seems so simple. I guess I better make a suggestion on their ideas board :D

  26. Thanks for the post John! I love the idea that you customize the CMS so that the client creates a “new project” that contains the specifically required custom fields. This could be an amazing plugin – customizing which custom fields are present depending on which page template is being used, or which “project” is being populated.

  27. @Bill, glad you like the post. There is a pretty intricate plugin out there called Flutter that helps do something similar. However, it’s way more complicated than I typically want.

  28. Hi,

    I’m a PHP novice, but I think this will create the image gallery I’ve been hoping for. Here’s the thing — I don’t know where to put the “$photos = aldenta_get_images();” call . . . My apologies for the remedial question.

  29. @Will, you’re going to have to know enough about PHP to print out the images. That call will put an array of photos attached to the post into the $photos variable.

    There is a comment I posted above on June 24th, 2009 at 10:09 am with code that does some very basic printing out of the image information that might help you get started.

  30. Thank you for this code. For some reason the gallery shortcode hasn’t been working correctly in several of my sites. This code, combined with some jQuery mojo to wrap links around the images, has really bailed me out.

    Thank you!

  31. Greate article! However i would like to have the thumbnails shown, but with an link to the fullsize image.

    i noticed that wp_get_attachment_image_src have an URL parameter witch wp_get_attachment_image does not seem to have.

    Does anyone have any idea how this would be solved?

    thanks!

  32. @Buffy, have you tried this to get the full size image?

    wp_get_attachment_image($photo->ID, 'full');
  33. When trying to get the title and caption, I end up with just the word Object on the front end. Do I need to change any other code? I’m a bit confused how to access the info that I am getting from the echo command.

  34. @Michael, it would take looking at your code in more detail and doing some PHP debugging. Are you using the latest version of WordPress, 2.9.1? The echo code is just an example. You’d need to be familiar with PHP and how to use the information after that.

  35. Hey John, thanks for these great pieces of code!

    I’ve successfully implemented the PDF module into my theme.

    Although I’m not a true php developer my work required me to build my own theme and load it with features to meet client requirements.

    The theme I’m building is called O Theme (O stands for Open).
    It is still early development but as soon as it gets enough features I’ll upload all source files and make it available for other designers.

    Do you mind if I use and modify your code? I’m writing an article for each feature I load into the theme and of course If you don’t mind I’ll write one for this feature and link to this page?

    Keep up the good work!

  36. @Dian, feel free to use the code snippets for whatever you need. I consider my WordPress code under the GPL just like WordPress – http://wordpress.org/about/gpl/

  37. i had to change

    $attachments = get_children( array(‘post_parent’ => $post->ID,

    with

    $attachments = get_children( array(‘post_parent’ => get_the_ID(),

    to make it work as I needed

    thanks a lot

  38. Excellent, just what I wanted. Cheerio!

  39. First of all, thanks John! – I was very happy to find this snippet of code to help me achieve what I’m going for…

    At this point, I’m able to output thumbnails of attached images in the case that a post has images attached to it; what I’m looking to do now is turn those thumbnail-sized images into links to the medium- or large-sized photos themselves.

    Perhaps someone has already explained how to do this and I’ve missed it (I’m sorry to bother if that’s the case!) – but I’ve tried a number of the modifications explained on this page and haven’t figured it out so far. Any ideas?

  40. Hi John,

    Thank you for this post! It helped me tremendously when putting together a custom gallery solution to meet a client’s specific needs. I took your code and ran with it a bit to allow people to create custom galleries and/or insert different size preview images at various spots in their WP themes. Maybe it can be of use to people who find your post:

    http://dameian.com/12/make-a-custom-wordpress-gallery-from-post-image-attachments/

    I am not a super php guy by any means, so there may be a better way to go about it than what I’ve done. Any comments or suggestions to help make it better are welcome.

    Thanks again!

  41. Just wanted to say a big thanks, been trying for ages to find a nice function to allow for pulling image info from a custom RSS2 feed.

    thanks!

  42. Hi there. Big thanks for the code, has been very useful so far.
    My only problem at the moment is that when you remove an image from the post, it will still be ouptut in the loop. Would you know how to ommit that?

    Many thanks again!

    Julian

  43. Thanks for the tip! I didn’t know about the “sort-by” property. Wonderful!

  44. Is there anything John can’t do? :) I love that a guy I know showed up in the search results for a PDF problem I was trying to solve!

    This post made me rethink an issue I had with a client. I ended up creating a page template that pumped out the page content in the main content area and I had a specific sidebar that I called so that any PDF attachments that were uploaded in that post were listed and linked in the sidebar even if the client hadn’t linked to them in the post.

    http://johnford.is.awesome as far as I’m concerned! :)

  45. Dang, this is a pretty sweet piece of code. I have a few plugins ideas I might implement based on this concept. Thanks for the tip John :)

Leave a Reply

Your email address will not be published. Required fields are marked *

*