Dougal Campbell's geek ramblings

WordPress, web development, and world domination.

Smarter Post Formats?

One of the new features in the upcoming WordPress 3.1 release is the introduction of “Post Formats”. The intent of this feature is that you can select the Format for a post, and themes can give different formats specific display styling. If you are familiar with Tumblr, then you might already have an idea of how that works. There is a specific set of formats available: Standard, Aside, Link, Status, Quote, Gallery, Chat, Image, Video, and Audio. The heart of this is in some new functions, has_post_format() and get_post_format(), which tell us which format is set for the current post (normally while in the loop).

There have been a few articles posted already with examples of how to add support for this in your theme. And they all made me think, “Really? That’s how they want to do it?” Because I thought that it would work a little differently…

The examples I’ve seen all follow this basic format (pseudo-code):

while ( the_loop() ):
  1.     if ( has_post_format( 'gallery' ) ) :
  2.         // big block of HTML to format a gallery post
  3.     elseif ( has_post_format( 'video' ) ) :
  4.         // big block of similar HTML to format a video post
  5.     elseif ( has_post_format( 'image' ) ) :
  6.         // big block of similar HTML to format an image post
  7.     elseif ( has_post_format( 'aside' ) ) :
  8.         // big block of similar HTML to format an aside
  9.     else :
  10.         // big block of similar HTML to format other posts
  11.     endif;
  12. endwhile;

Those ‘big blocks of similar HTML’ inside if/elseif blocks bother me. When you are trying to edit a section of code like this, it can be very easy to lose your place. When I first heard about post formats, I thought we were talking about a new set of files in the template hierarchy. I figured that we would be breaking out the code for each format into their own files.

You see, we also recently got this nifty new function in WordPress 3.0 called get_template_part(). The TwentyTen theme uses this function to import different loop code depending on whether the visitor is currently viewing the homepage, a post, a page, or an attachment. The get_template_part() function helps your theme conditionally pull in variant blocks of code pretty easily. Being able to break these pieces out makes the theme easier to maintain, because you don’t have multiple subtly-different chunks of code embedded into multiple larger template files, with conditional if/elseif blocks to manage them.

For example, in TwentyTen’s index.php, there is a call like this:

get_template_part( 'loop', 'index' );

Which means: Look for a file named ‘loop-index.php’ in the current theme; If you don’t find it, look for ‘loop.php'; If this is a child theme, and you don’t see either of those templates, look for them in the parent theme. Each of the major templates (‘archive.php’, ‘author.php’, ‘category.php’, etc) makes a call similar to this, looking for a loop template specific to the appropriate view.

And I thought that a marriage of get_template_part() and get_post_format() was pretty obvious. You break your formats out into separate template files, and use get_template_part() to decide which template to load. So when I wanted to quickly hack up a temporary theme for the WordPreh site (which you should tell all your friends about), I put my idea to the test. I tore the guts out of the loop files, and created a set of format template files. My loop simplifies from the huge if/elseif block above down to this:

while ( the_loop() ):
  1.     get_template_part( 'format', get_post_format() );
  2. endwhile;

get_template_part() plus get_post_format() equals teh awesome!

So, when I’m displaying my list of posts, if the current post has post format ‘Link’, then we look for a file named ‘format-link.php’. If the current post has format ‘Aside’, we look for ‘format-aside.php’, if it’s a Quote, ‘format-quote.php’, regular posts look for ‘format-standard.php’, and failing all else, we use plain old ‘format.php’.

In the case of WordPreh.com, most of our posts use the ‘Link’ format, which is formatted radically differently from normal, beause I want the headline to link directly to the site URL in question (mostly Twitter statuses, sometimes blog posts) instead of the local permalink. So my ‘format-link.php’ template is quite different from most of the other ‘format-*.php’ templates.

The advantage in breaking these formats out into separate templates is that it lets me focus on just the block of code that I’m concerned with. I don’t have to hunt though 200 lines of loop code to find the right bit amonsgt a lot of similar looking bits. I only have to examine the 35 or so lines that affect the formatting for the particular view I’m concerned with. The disadvantage is that I have more loop and format files in my theme to keep track of, but I think it’s a pretty good trade-off.

So what do you theme developers think? Is this a step forward?

About Dougal Campbell

Dougal is a web developer, and a "Developer Emeritus" for the WordPress platform. When he's not coding PHP, Perl, CSS, JavaScript, or whatnot, he spends time with his wife, three children, a dog, and a cat in their Atlanta area home.
This entry was posted in WordPress and tagged , , , , , , , , , , , , . Bookmark the permalink.

56 Responses to Smarter Post Formats?

  1. This makes all the sense in the world!

    get_template_part() plus get_post_format() equals teh awesome!

    … I could not agree more. Makes me want to go write a new theme using this method right now!

  2. Pingback: Tweets that mention Smarter Post Formats? #wordpress -- Topsy.com

  3. curtismchale says:

    Thanks for the link and yeah this is the way to do it. Going back to amend my article so it links here with a better way to do it.

  4. Dougal says:

    Will Anderson points out that get_template_part() is a performance hit, because you are including templates, potentially several times in a page view. He suggests moving the post format templates into functions: Even Smarter Post Formats.

    I think that an opcode cache like APC or XCache will mitigate that problem. And of course, page caching like from WP Super Cache or W3 Total Cache would, too. But it’s still something to keep in mind for sites that need to squeeze every bit of performance out.

    • Chrispian says:

      Nice work. Think it should be that way by default. Everything that can be styled in WP should have it’s own template part. Would make theming much easier.

      As for the performance hit, I don’t think WP stands up very well on it’s own under stress anyway (not faulting it, every cms that uses a database runs into this issue) so using a cache is pretty much mandatory for me these days anyway.

      Thanks for posting the tip. Going to be using this on the relaunch of my sites.

    • Chip Bennett says:

      As I posted over on Wil’s blog post:

      The other problem with his approach is that you lose the Parent/Child Theme template-file hierarchy inherent in get_template_part(), thanks to its call to locate_template_part().

      There’s a lot of awesomeness built into get_template_part() that, IMHO, far offsets any potential PHP performance hit the function incurs.

  5. Thanks for the mention :)

    You’re probably right about APC, XCashe and page caching plugins making it irrelevant, though if a theme developer is distributing a theme, they can’t know what the user has installed.

    That being said, you’d have to benchmark the differences to decide whether they’re even worth worrying about. In all likelihood, they’re not.

  6. Matt W. says:

    Definitely seems the way to go to me and it seems similar to the methodology in Alex King’s Carrington themes I would say.

  7. Dougal, I agree with you here. The giant blocks of conditional html intermixed with php are really confusing to me. I use a similar method to what you suggest here. I created a router file that I include in all loops throughout the theme and looks something like this:

    <?php
    
    $format = get_post_format();
    $format = ! empty( $format ) ? $format : 'default';
    
    if ( isset( $post->post_type ) ) {
    	switch( $post->post_type ) {
    		case 'post' : 
    			get_template_part( 'post', $format );
    			break;
    		case 'page' : 
    			get_template_part( 'post', 'page' );
    			break;
    		case 'mfields_bookmark' : 
    			get_template_part( 'post', 'bookmark' );
    			break;
    		default :
    			get_template_part( 'post' );
    			break;
    	}
    }
    ?>

    view it at pastebin

    I decided to use “post” as a base for the template files – believe it or not there currently is no template named “post” in the current template hierarchy. I think that it’s really important to have the loop code separate from the post’s presentation markup. This makes it easily reused in other areas especially admin-ajax.php.

    • That’s pretty similar to the Drupal approach, and one of the few things I like better about Drupal. Of course Drupal’s approach bakes in too much rigidity so it is not ideal either. But I agree; I really wish WP had a well though out model for templates files for individual posts instead of requiring the theme to always code the loop.

  8. Pingback: Smarter Post Formats? Use Carrington | alexking.org

  9. Jeremy Clarke says:

    One scenario where the non-smarter system excels is if most of the formats are the same. In those if clauses you could include as many ORs as you want, so you only have to have one block for gallery, image, etc. Followed by one extra block for your oddball format. This keeps it much simpler than your system and is still easier to read.

    I’m also with Will: always break logic into functions if it is at all possible. Basically any time you have a control structure, including the loop, you should break it into a function and call it as much as possible, it’s so much cleaner. I find template parts are often a kludgy hack for situations that could be elegantly executed using functions instead.

    For parent/child themes the solution is easy: wrap the function in function_exists() so that the child theme can override it if necessary, and write up an API doc for your theme instead of a Byzantine template part reference.

  10. Pingback: WP'it

  11. @Dougal “The advantage in breaking these formats out into separate templates is that it lets me focus on just the block of code that I’m concerned with. I don’t have to hunt though 200 lines of loop code to find the right bit amonsgt a lot of similar looking bits.”

    +1. I wish more WP developers thought like that. I’ve had to read and/or clean up far too much code like that.

    • Dougal says:

      Yeah, it’s a similar idea to the common practice of “If a block of code grows to be more than X lines, you should probably break it into smaller functions”. It helps keep the main logic of the code at a higher level.

  12. Pingback: Wordpress Post Format

  13. Pingback: Michael Fields » My First Post Format

  14. Chip Bennett says:

    I finally started playing around with Post Formats in 3.1RC2.

    One caveat: get_post_format() doesn’t return a string if format = “standard”. Thus, the resulting code isn’t as clean as it could be.

    This:
    get_template_part( 'format', get_post_format() );

    Becomes this:
    if ( has_post_format() ) {
    get_template_part( 'format', get_post_format() );
    } else {
    get_template_part( 'format', 'standard' );
    }

    In order to display format-standard posts.

    (Unless I’m missing something…?)

    • Chip Bennett says:

      I suppose I could alternately add a template file called “format.php”, which should return when get_post_format() returns NULL… but that’s non-intuitive, also.

      • Otto says:

        Yes, a plain format.php would work as the fallback position. “Standard” is actually the lack of any post format. This is why I liked “Default” better as it made this more clear, to me. But some people don’t like that wording.

        • Dougal says:

          That’s what I did in the WordPreh theme: I’ve got a ‘format.php’ as the standard fallback. Even if get_post_format() was returning ‘standard’ and thus calling to a ‘format-standard.php’ template, having a bare ‘format.php’ would still be a good idea, in case of any weird breakage in the future.

      • Chip Bennett says:

        I’ve got it!

        I’ll rename “format-foo.php” as “post-format-foo.php”; that way, I can have a “post-format.php” that becomes the (more-intuitive) fallback.

    • Dougal says:

      The ‘standard’ post format is a special case. Looking at other parts of core, (like the get_post_class() function), you’ll see that they check for an empty post-format in places where they need to display ‘standard’. Kind of annoying now that I think about it. Seems like get_post_format() would be the perfect place to standardize it.

    • ben david says:

      i’m a newbie with this, can you please give an example for a format-XXX.php file?

      so i can know how should it look like more or less?

  15. How did you implement the Link format?
    It seems that the whole content block should be made to a link, or that the link url should be placed in the title or the content. But then you would have parse the diffrent variations trying to extract the right link, and then generate the content and the title for display.

    Other plugins seems to use a custom field for the title url.

    I can’t see any code example for how it’s supposed to work in 3.1.

    How did you do it?

    • Dougal says:

      I have a custom function which extracts the first link from the post content. It checks for either a raw URL on a line by itself, or for the first <a href=”…”> that it finds, and considers that “the” link for the post.

      I’ll be sharing the code when I get time to write it up.

  16. Rev. Voodoo says:

    Well, after reading all the articles out there…. about post formats.  Starting with Lisa Sabin-Wilson’s article, then on to this one, and on to the Even Smarter Post formats article…. I had myself good and confused.  What I was really after was to offload all my templates to loop.php so every template could have the loop overwritten by a child theme.  But then I wanted to have formats, which could also be treated the same way.  Maximum child theme useability if you will.  I’m really new to all this…. coding things according to my own thought process.  But here’s what I came up with:
    http://go.rvoodoo.com/WPformats
    I’m not sure if this is even a good way to go about it….. but it seems to work well for me.  Any loop or format can be child themed.  Your article was one of the 3 that really got me thinking about it, so thanks!

  17. Pingback: » Additional Resources

  18. Dan says:

    Just test this out on my site. Works like a charm. Thanks a bunch!

  19. Ryan Dennler says:

    Very nice tip, I will definitely have to start hacking away at my loop files and make my own post format content chunks! Thanks!

  20. Pingback: WordPress Post Formats  | prosoxi.com

  21. Pingback: Mini entrada | DEMO EMPLATE v10

  22. Pingback: WordPress 3.1 (Reinhardt) Features: New CMS Capabilities and More | Free Wordpress Themes at KiloWordpress.com

  23. Keisa says:

    So what files are needed in order for that code to work? loop.php?? I don’t really understand where I’d add that line of code :(

    • It depends on how your current theme is organized. Wherever your theme puts ‘the loop’ is where you would make the changes. That might be in one or more ‘loop.php’ files, or it might be in ‘index.php’, ‘page.php’, ‘single.php’, etc.

      If you want to see a full implementation of the Smarter Post Formats idea, check out my Formattd Theme. Start with ‘index.php’. It uses get_template_part() to pull in ‘loop.php’ (actually, it looks first for ‘loop-index.php’). This in turn checks the post format of each post, and attempts to load the appropriate ‘format-[something].php’ file.

      Then the files like ‘format-image.php’, ‘format-quote.php’, or the fallback ‘format.php’ contain just the code to format a single entry of the given format.

      Hope that helps!

      • Keisa says:

        Appreciate the fast response :) I will definitely try that! And post results when I’m done! Thank you for your help!

      • Keisa says:

        I ended up copying a few snippets from the Formattd Theme.

        1.
        This code works perfectly fine.
        But, the code you listed in your post isn’t as long as the one above.
        I tried replacing it with //

        But an error pops up//

        Fatal error: Call to undefined function the_loop() in /home/****/public_html/test/wp-content/themes/themename/loop.php on line 1

        Do you mind giving me a little explanation so I can understand why it doesn’t work if I alter the code more..?

  24. Pingback: How to display post formats?

  25. Keisa says:

    I have another question, is a loop-single NEEDED in order to display gallery, quote, ect single posts differently? Right now my theme only has single.php with these lines of code to display single gallery posts //
    ID ); ?>
    then the else tag and HTML for regular single posts…

    The single posts are all messed up. the content is displayed before the title and date…

    before I created post-formats it was perfectly fine, positioned where it should be…Any idea what might have caused this issue?

  26. Keisa says:

    Figured it out :) Thank you for your help earlier!

    • Great! I had started to reply yesterday, but got tied up with work and never had a chance to finish it up. Glad you were able to work things out!

      • Keisa says:

        I just had to update my single.php file :)

        Everything is working perfectly!

        Except I’m not sure how to style the single posts differently…
        The format-gallery.php has a thumbnail for the posts page.

        But I’d like to remove the thumbnail if possible.

        I’ll browse the site to see if there is a solution :D

  27. Keisa says:

    Hello :) It’s been a while since I last commented. I was curious to know if there is a way to style the format posts differently from the single post pages. For example if I have a video post on the main posts page I’d like the video to be maybe 200px width and 150px height with an excerpt on the right hand side. then when the viewer clicks read more the video will be larger and the excerpt will turn into full content underneath the video. Right now the code within the format-video.php appears the same on my blog page :/ Is there a solution to this?

    • Keisa says:

      Really hoping for an answer to this :/

      • @Keisa – Your home page should have a body class of ‘home’. On a single post page, you’ll have classes for ‘single’ and ‘single-post’ (pages will have class ‘page’). The format-specific posts will also get a class like ‘single-format-video’. So you can change styling based on those.

        As for changing image sizes and excerpt versus full post content, look at the ‘single.php’ and ‘loop-single.php’ in the Formattd theme. These are the templates used when viewing an individual blog post (vs ‘page.php’ and ‘loop-page.php’ for pages).

  28. Keisa says:

    I saw your response, but it appears you’ve deleted the comment? I’ve sent you an e-mail, if you’re not too busy to help me out :/

  29. Pingback: Creating Post Formats | (Re)Learning Wordpress Development

  30. Pingback: ? ?? | wordpresscoop.co.krwordpresscoop.co.kr

  31. Pingback: Post Formats and Content Templates in the Toolbox Theme | ThemeShaper

  32. Pingback: Function Reference/get post format | ???

  33. Pingback: ? ??, ?? ??, ???, ??, ???, ??, ??, ???, ???, ??, aside, gallery, link ?

  34. Pingback: Step by Step Guide to WordPress Post Formats | Shade Tree Sites

  35. Pingback: WordPress?????get_post_format – Kraddy WordPress

Leave a Reply

%d bloggers like this: