Skip to content

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.

Happy Earth Day!

play station shirt

As you can see, I’m sporting one of my favorite shirts today.

Since I’m a geek, and have fun electronics, I try to keep everything turned off and unplugged when not in use. The laptop gets powered down at night and the power strip switched off where all of the electronics are plugged in. Actually, in support of Earth Day I think I should keep everything turned off and skip work…

What do you do to help out the Earth?

Meetup: Intro to WordPress

Triad Web Meetup

This meetup I’ll be covering how to install WordPress from scratch, getting started with creating/modifying a WordPress theme, the basics of the admin and show some examples of what can be done with WordPress as a CMS.

Bring your questions and any WordPress sites that you’d like to show the group. All skill levels should be able to take away something from the presentation.

What: Intro to WordPress
When: April, 22 2009 7:00pm - 8:30pm
Where: Greensboro Public Library Downtown (take a right as soon as you walk in and head to the end of the hall)
RSVP: Triad Web Meetup

These events are always free and everyone is welcome so please spread the word!

Stop Mailing Me Phone Books

With Google’s local search, and sites like YellowPages.com, I haven’t opened a phone book in years. The printed books are such a waste of resources and time. I also get the same book delivered to my home and work addresses.

I contacted YellowPages.com via email and they were nice enough to give me a list of local providers who are responsible for phone books. So, I called Bell South, my local book provider, and removed both of my addresses from their mailing list.

  • AMERITECH: 1-800-346-4377
  • BELL ATLANTIC/VERIZON: 1-800-346-9639
  • BELL SOUTH: 1-800-682-4000
  • GTE: 1-800-346-9639
  • MCI: 1-800-444-3333
  • PAC BELL: 1-800-848-8000
  • SWBELL: 1-800-792-2665

Get rid of these monstrous books and help save a tree (and fuel, paper waste, water, forest animals, money and everything else that’s connected to producing a phone book)!

Happy 25th Birthday Macintosh!

Apple Macintosh
Marcin Wichary

iWork.com - Google Docs Competition?

I love the free apps that Google provides (especially the incredible spam-blocking e-mail), but I’m really excited to see Apple’s iWork go web-based. It currently appears that you can only “share” documents online and not edit them, but I imagine that’s the next step. The documents look exactly the same in the application or in their beautiful web interface and notes can be added by reviewers. Can’t wait to see where this one goes.

iwork.com

Recent Work: abitareshop.com phase 2

abitare

Phase 2 of a beautiful project I’ve been working on with Tina (swissmiss) went live last month. Now abitare has a full online checkout! The site is built on WordPress with a shop plugin used to manage products and a completely custom front-end theme and checkout process that hooks into authorize.net to accept credit card payments.

It’s the perfect place to order holiday gifts!

Recent Work: lawyeravenue.com

Lawyer Avenue

I had the pleasure of working with the fantastic designers at Design Commission out of Seattle to build an e-commerce/blog/content site for their client Lawyer Avenue. The site went live last month and is a custom blend of WordPress and Magento.

Plugin Update: PDF Bookmark bug fix and French translation

If you are having problems with the bookmark plugin not working for some documents, this update (1.2) should fix that. The update also adds a French translation to the Bookmark menu and provides an installation path for Linux users. Thanks to TitCouille for help with all of those items.

The plugin should work correctly for Adobe Reader 7, 8 and 9. If you’re interested in helping add a translation for another language please let me know. There are currently only 3 items that need translating - “Bookmark”, “Bookmark This Page” and “Go To Bookmark”.

See the full details and download the plugin.

Phusion Passenger (mod_rails) Memory Management

I’ve been using Phusion Passenger (mod_rails) for about a month to run a production and staging machine with a Ruby on Rails app. So far things have been going really well. Installation was smooth and it’s been really peppy.

However, the app just got hit by a lot of people at once and stopped responding. I didn’t realize the default setting in Passenger is to spawn a max of 6 Rails instances simultaneously. The documentation recommends 2 instances for a VPS with 256MB of memory (almost exactly what I’m running). So, my server spawned the max and then ran out of memory which made it unresponsive.

I hit a couple of small walls while getting this working so I wanted to share the process.

On linux based machines you can run passenger-status to find out the number of Phusion Passenger application instances that are running.

----------- General information -----------
max      = 6
count    = 3
active   = 0
inactive = 3

----------- Applications -----------
/u/apps/myapp/releases/20080921194503:
  PID: 8792      Sessions: 0
  PID: 8789      Sessions: 0
  PID: 8784      Sessions: 0

You can see that the output show the default max value of 6. To change this number you need to edit your httpd.conf and set the PassengerMaxPoolSize option. Make sure this is outside of your VirtualHost or it won’t work… which, I obviously ran into. It should probably look something like this:

LoadModule passenger_module /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.3/ext/apache2/mod_passenger.so
PassengerRoot /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.3
PassengerRuby /usr/local/bin/ruby
PassengerMaxPoolSize 2

Once you’re done with that restart Apache and Passenger. Now, to take a look at the memory that Apache and Passenger are using run passenger-memory-stats. You’ll see something like this:

------------- Apache processes -------------
PID   PPID  Threads  VMSize   Private  Name
--------------------------------------------
5842  1     1        10.3 MB  0.2 MB   /usr/local/apache2/bin/httpd -k start
8757  5842  1        10.4 MB  0.3 MB   /usr/local/apache2/bin/httpd -k start
8784  5842  1        10.4 MB  0.2 MB   /usr/local/apache2/bin/httpd -k start
9137  5842  1        10.3 MB  0.2 MB   /usr/local/apache2/bin/httpd -k start
9141  5842  1        10.4 MB  0.2 MB   /usr/local/apache2/bin/httpd -k start
9143  5842  1        10.3 MB  0.2 MB   /usr/local/apache2/bin/httpd -k start
9147  5842  1        10.4 MB  0.3 MB   /usr/local/apache2/bin/httpd -k start
9155  5842  1        10.4 MB  0.3 MB   /usr/local/apache2/bin/httpd -k start
9163  5842  1        10.4 MB  0.3 MB   /usr/local/apache2/bin/httpd -k start
9506  5842  1        10.4 MB  0.3 MB   /usr/local/apache2/bin/httpd -k start
9510  5842  1        10.3 MB  0.2 MB   /usr/local/apache2/bin/httpd -k start
9623  5842  1        10.4 MB  0.3 MB   /usr/local/apache2/bin/httpd -k start
9629  5842  1        10.3 MB  0.2 MB   /usr/local/apache2/bin/httpd -k start
9631  5842  1        10.3 MB  0.2 MB   /usr/local/apache2/bin/httpd -k start
9633  5842  1        10.3 MB  0.2 MB   /usr/local/apache2/bin/httpd -k start
9750  5842  1        10.3 MB  0.2 MB   /usr/local/apache2/bin/httpd -k start
9752  5842  1        10.3 MB  0.2 MB   /usr/local/apache2/bin/httpd -k start
9865  5842  1        10.3 MB  0.2 MB   /usr/local/apache2/bin/httpd -k start
### Processes: 18
### Total private dirty RSS: 4.36 MB

-------- Passenger processes ---------
PID   Threads  VMSize   Private  Name
--------------------------------------
8749  20       6.0 MB   0.5 MB   /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.3/ext/apache2/ApplicationPoolServerExecutable 0 /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.3/bin/passenger-spawn-server  /usr/local/bin/ruby  /tmp/passenger_status.5842.fifo
8758  1        5.5 MB   2.9 MB   Passenger spawn server
8789  1        61.6 MB  53.7 MB  Rails: /u/apps/myapp/releases/20080921194503
8792  1        61.8 MB  53.9 MB  Rails: /u/apps/myapp/releases/20080921194503
### Processes: 4
### Total private dirty RSS: 111.03 MB

Now, that may look like a lot of Apache instances running but you can see the “Total private dirty RSS” (real memory usage of the processes) is only 4.36 MB which is nothing in the scheme of things. More importantly, the real memory that the Rails instances are taking is 111.03 MB which my server can handle. Remember, you’ll probably have MySQL and other applications running along with these processes, so don’t up the PassengerMaxPoolSize to the point of bringing your server to its knees.