PureNews

PureNews is an amazingly sleek and powerful news theme with unlimited color variations.

View full feature list Check out the live demo Buy this theme today

Mixing Gallery and Blog Posts

Posted by on 3rd Aug 2008 | 17 comments

This is part 3 on using the built in WordPress Gallery features. Part 1 and Part 2 are recommended reading also.

So, you’ve created a few galleries, you’ve got your single image page looking spot on with all the details and EXIF data displaying. However when you create a new gallery what happens on the front page of your site? If you’re display the full post, the whole gallery will display. If you’re displaying an excerpt, you’ll get a short excerpt if you’ve set one. Personally I like the way Matt Mullenweg has set his blog up. You get the full post if it’s a standard blog post, but if it’s a new gallery it will display a thumbnail from the gallery, along with a short excerpt and the number of photos in that gallery.

So how can we mix these together on the front page? First off we need to ensure that the code we put in place only affects the gallery posts and not the standard posts. So this is easily done by checking which category the post is in:

<?php if (in_category('3')) {
// add our code for dealing with a gallery post here
} else {
the_content();
} ?>

Note, the ID of 3 used above is the category ID. You’ll need to check your categories and replace 3 with the ID of your gallery category.

Now we need to work out the code.

Retrieve a Photo

To get a photo we take the ID of the gallery post and use the get_posts() function to retrieve the images associated with that post. This is relatively easy and the following code will get one image randomly for us:

$args = array(
'post_type' => 'attachment',
'numberposts' => 1,
'post_status' => null,
'post_parent' => $post->ID,
'orderby' => 'rand'
);
$attachments = get_posts($args);
foreach ($attachments AS $attachment) {
// code to display the image goes here
}

The above code will randomly pull out just 1 attachment connected to the post currently being displayed in the loop. We then use the foreach() loop to retrieve the information from the $attachments array. We can retrieve any information from the database record for this image, however we just need the URL of the image, the title of the image and its record ID ie.

$alttxt = $attachment->post_title;
$imgid = $attachment->ID;
$fileurl = $attachment->guid;

Unfortunately that’s not all there is to it for getting the thumbnail. The $fileurl value will contain the original image’s URL, ie. our large version. We need to display the thumbnail, not the large file. When an image is uploaded it will be resized into a medium and thumbnail size. All 3 files are stored in the same location as

  • Original: filename.jpg
  • Medium: filename-600×400.jpg
  • Thumbnail: filename-150×100.jpg

The second two filenames are basically filename-widthxheight.jpg so these figures will depend on your settings under Options – Miscellaneous.

So, we need to make filename.jpg become filename-AxB.jpg where A and B are the width and height of your thumbnail. Luckily we can use the EXIF data to work out the size of the thumbnail and added that into our image filename:

$meta = wp_get_attachment_metadata($imgid);
$imgw = $meta['sizes']['thumbnail']['width'];
$imgh = $meta['sizes']['thumbnail']['height'];
// now get the file extension and take it off our file url
$imgext = substr($fileurl, -4);
$fileurl = substr($fileurl, 0, -4);
// and now put it all together
$fileurl = $fileurl."-".$imgw."x".$imgh.$imgext

It’s a bit messy, but it will do the job. Whilst you can get the thumbnail file path directly from the EXIF data, this is the full file path and not the URL path, so at present the above is the best way I’ve found.

Count the Photos

It’s nice to be able to say how many photos are in the gallery, and this is easily done with a slight code change to the above. Instead of retrieving just 1 attachment we can retrieve them all, count how many are returned, but force the foreach() loop to only display 1. To retrieve all the attachments we change the line in our arguments array for the get_posts() function to

'numberposts' => -1,

Then to get the number of attachments returned we use the PHP array count() function once the get_posts() function as been executed:

$noimages = count($attachments);

The last thing we’ll need to do is make the foreach() loop only run once, so we use the break; command, which will break out of the loop.

The Final Code

So putting all of this together we get the following code:

[sourcecode language=”php”]< ?php
if (in_category('3')) : // is a gallery post so alter the display
$args = array(
'post_type' => ‘attachment’,
‘numberposts’ => -1,
‘post_status’ => null,
‘post_parent’ => $post->ID,
‘orderby’ => ‘rand’
);
$attachments = get_posts($args);
$noimages = count($attachments);

if ($attachments) {
?>


A PHP Developer using WordPress to power both blogging and commercial CMS sites. I've written and released a couple of plugins for WordPress and am currently writing plugins for use on commercial websites.

17 comments - Leave a reply
  • Posted by Richard Bui on 3rd Aug 2008

    Sarah,

    You're 3 part series on the new WordPress Gallery is excellent! It's been extremely helpful for my new theme!

    Keep up the good luck!

  • Posted by willy on 3rd Aug 2008

    thanks for your guide, i will try it in my blog.

  • Posted by Sarah on 3rd Aug 2008

    Cheers both. Richard glad I could help :)

  • Posted by slee on 4th Aug 2008

    wicked! Great series of posts :)

    just one thing though.

    If i have set this up to use "pages" how can i do the same thing?

  • Posted by Sarah on 4th Aug 2008

    Cheers Lee. If you're using pages for your gallery then the above won't apply as the front page and archives/categories only list posts, not pages :)

  • Posted by slee on 4th Aug 2008

    sorry should of been more clear :P

    what i want to do is to have the gallery main page list out the galleries so from what you have said i just make a page template and use the loop and make it get the child pages of the page it is on

  • Posted by Sarah on 4th Aug 2008

    Ah yes. Okay, assuming you have a Galleries Page then your galleries are child pages of this page then use get_posts() to create a loop on that page getting all the child pages, and then go from there using the code above. :)

  • Posted by Grant H on 11th Aug 2008

    Hello again Sarah.

    Your posts have been the closest thing to me getting my Blog just how I’d like it, but I’m in a bit of a pickle in terms of how to overcome my next hurdle. There are 2 things I’m trying to do at the moment, and I’m finding it nigh on impossible to solve them.

    Firstly, I’m wanting to have a conditional sidebar that displays the EXIF information ONLY if the post includes a photograph (or, in an easier case, if the post resides in the ‘Daily Image category) Currently the EXIF post you made helps me when viewing the ‘attachment’ page, but not a single post.

    I’ve been thinking that what I need to do, is create a variable that retrieves any attachement id’s in the post, and wrap that in a conditional piece of code that only displays it if it’s in a certain category. If you take a look at http://photogrant.co.uk/blog/?p=82 and see the difference between that (and then click on the image that links to its attachment page) – you’ll notice the first only displays the fact I wrote the article, and where I’ve placed it, but not the exif information of the photograph I uploaded.

    Secondly, and I’d hate to burden you with another problem – I’ve got this image displaying on my own home page, that utilises the ‘loop’ in that I’m filtering the content to display 1 picture on the home page, and nothing else. What I’m trying to implement, is a way to click a link, and have the previous post in that category displayed instead. Now, the way in which it’s done at the moment, the previous_post_link goes to the blog area, and the single_post that’s chronologically previous to the one on the home page. I’m trying to keep within the confines of index.php and have that display the previous post. instead of linking elsewhere? Is that possible? The idea is here http://www.photogrant.co.uk/index.php

    I’m sorry if all of the above made no sense at all. I’ve only had wordpress for 2 weeks, and coded only for 1, I’m trying to pick up the lingo and the likes as fast as I can!

    Much appreciated,
    Grant.

  • Posted by Sarah on 12th Aug 2008

    Hi Grant,

    Okay, answer to your first question. If the post is in a specific category then you can use the in_category() function to check if the post is in that category, if it is then grab the attachment IDs associated with that post and make them global (eg. in an array) and then you can access that in your sidebar and grab the details you need. However if you have more than a couple of photos your sidebar will become quite long.

    If the post isn't in a specific category but it does contain an image then it's a bit tricker. It is possible but with this being your first week of coding and second week of WordPress I don't want to baffle you (although I've probably already done that!). To be honest, the easiest solution would be to create a new category that you always mark off when you've got a photo in your post, then use the solution above. You don't have to show this category on the front end as you can exclude it from the wp_list_categories() function (see my earlier post on how to do that). That would be the easiest option and probably the one I'd use.

    For your second question, if I've got this right, you essentially want your front page to randomly display a daily image and then you have next and previous to the next and previous images in the daily image category? (by the way your link didn't work for me). You may need to set your front page to use that specific category as the front page, then use query_posts() to make it retrieve a random post (use orderby=rand or something similar) and set the number of posts to 1. Then theoretically your next and previous links will automatically display the next and previous posts in that category. It's not something I've tried though.

    Easiest option is to try putting those into practice and then if you only get so far (so it doesn't work as hoped), post up in the blogging tips forums with your code plus working links, and I can take a better look and see what may need altering.

    Hopefully that makes sense!

  • Posted by Grant H on 12th Aug 2008

    Sarah, I really appreciate your reply!

    I guess yesterday I didn't quite explain myself in enough detail, as re-reading what I put, I seemed to confuse myself! What you described (making 1 category solely for front-page images and excluding it from the initial blog roll) I'm already doing!

    After much deliberation, I've decided to use my 'front' page area seperately from my blog, and employed PixelPost to power that side. As messy as it is, it seems to allow me to keep all areas of my website seperate, and that benefits me mentally, more than anything.

    This theming business, and php endif() zero 1, 2 DEATH – It's just sooo much to grasp. I really, really appreciate your articles – they've helped me no end :D

    Thanks again Sarah,

    Grant.

  • Posted by Sarah on 12th Aug 2008

    Okay, so if your photo is always in the daily image category then in your sidebar you can use the following code:

    if (is_single()) :
    global $post;
    $categories = get_the_category();
    $catID = $categories[0]->cat_ID;

    if ($catID == X) : // where X is the ID of your daily image category
    $args = array(
    'post_type' => 'attachment',
    'numberposts' => -1,
    'post_status' => null,
    'post_parent' => $post->ID
    );
    $attachments = get_posts($args);

    if ($attachments) {
    foreach ($attachments as $attachment) {
    $imgid = $attachment->ID;
    $meta = wp_get_attachment_metadata($imgid);
    // output your EXIF here for each photo
    }
    }
    endif;
    endif;

    To break it down, first it checks if you’re on a single post page. If so then it sets up the $post details to be used and gets the category of the post. Then it checks if the category is the correct ID, if so it gets all attachments for that post and loops through each one and sets up the $meta variable for use to access the EXIF data, which you can then add in yourself using the info I’ve listed.

    Hopefully that will do what you need? Let me know how it goes :)

  • Posted by Roger Coathup on 18th Sep 2008

    Hi Sarah,

    thanks, this should be really useful in a magazine site I'm developing for a client.

    How would the code cope if the attachments include pdf files as well as images? Is there anyway to distinguish between attachment types?

    I'm planning to integrate your code ideas with a script that automatically resizes images on the fly (I need more sizes than the thumbnail, medium and full defaults). I'll let you know how that goes.

    A further question: is it simple to integrate lightbox? i.e. so that clicking on images displayed using the gallery shortcode, are rendered in lightbox.

    Thanks,

    Roger

  • Posted by Roger Coathup on 20th Sep 2008

    Hi Sarah,

    after a bit of searching, I came across get_children(), where you can specify attachment type.

    The code:

    $images =& get_children( 'post_type=attachment&post_mime_type=image' );

    might be a tighter way of getting your image list from the post.

    Cheers,

    Roger

    p.s. you've got me digging a lot deeper into WP than I would have done otherwise (your post was a bit of a 'eureka moment' for me)

  • Posted by Sarah on 20th Sep 2008

    Hi Roger, sorry was away for a few days hence not replying sooner. Glad to see you found the code. get_children() has come about since 2.5 so is the best solution to use if you have multiple file types.

    In regards to the lightbox, it depends where you want the lightbox. If you want a gallery of thumbnails and you want the lightbox on those then you'd have to run the output through a string replacement or preg_replace() function to insert a rel="gallery" type attribute in each link. Probably search for '<a href' and replace it with '<a rel="value" href' would work. It's not something I've tried as my own WP driven gallery is set up to have the individual page for each large image plus its description and EXIF data, plus comments.

    However the str_replace() should work easily enough if you're at all familiar with a bit of basic PHP. Glad to hear you're digging into WordPress, it's not so bad once you've got your head into the Codex! :)

  • Posted by kristarella on 18th Nov 2008

    Just wanted to say a big THANK YOU for these tutorials. Greatly appreciate them.

    I imported my photoblog from some other software, so the metadata for the photos isn't quite kosher for the old posts.

    I was able to get the size of the thumbs using

    <code>wp_get_attachment_image_src($post->ID, 'thumbnail', false)</code>

    Which outputs an array containing the image file URL [0], width [1], height [2]. That, in combination with your code to remove the extension and add the thumbnail dimensions to the filename works very nicely.

  • Posted by Sarah on 19th Nov 2008

    Glad to have helped kristerella :)

  • Posted by nitgreen on 5th Jan 2011

    Sarah,

    Brilliant post indeed! ,

    Thank you for the work you have put into this post,

    It helps clear up some questions I will bookmark your blog because your posts are very informative

    Keep up the good luck !