12 - Implementing Blog Detail Templates

So far we’ve done a good job implementing the index view of our Tumblr style blog with its mixed content types.  Now we need to create single-entry views for those entries so each one can be bookmarked, commented on, and available to search engines.

Download the EE Code for 12 - Implementing Blog Detail Templates

Wide or Deep?
Like so many times in EE development the question becomes - do I go wide (more but simpler templates/Snippets) or deep (fewer but more complex templates/Snippets)?

In this specific case the Snippets we created for the blog index are mostly correct. The biggest thing we don’t want are the titles to be linked if you already followed the link. So do we make the existing Snippets more complex to centralize logic or just put the code in the single-view templates? I decided to use conditionals in Snippets - then all the picky date formatting and meta information are in one place for each post type. This will also centralize most of the display logic for each content type - if you decided you wanted to use a different lightbox script, etc it would only need to be changed in one Snippet.

Template Starting Point
I noted that the Folder HTML template pack came with a catch-all ‘single’ template that we can make use of here. It adds a masthead element and marks up the title areas differently.  It also includes comment and comment submission form styling that we’ll soon make use of.  I did chunk the comments code into a new Snippet - I’m not sure if they’ll stay that way but I just needed to centralize them for now.

Anatomy of a Single-Entry Template
Let’s look at one of the new single-entry templates and talk about what’s happening in it. Once you have a sense of the functionality for one they should all make good sense.

We’ll look at the blog/post template:

{exp:channel:entries channel="blog_post" limit="1" disable="pagination"}    

="embeds/header" my_body_class="single" my_active_nav="blog" my_page_title="Blog | Post | {title}"}                

<!-- masthead -->
div class="masthead cf">
A Blog Post
ENDS masthead -->    

posts list -->
div id="posts-list" class="cf">            
ENDS posts list -->


You’ll note the channel:entries tag now wraps around the entire template. This way I have things like the title variable available to both display and pass off to the embeds/header template. The body class is now “single” - this triggers the CSS to put the meta information under the post rather than alongside it. I limit the channel:entries tag to 1 just to ensure that even if someone hacks the URL the template won’t load multiples - the way this is coded that would be bad.  All I can disable is pagination - I’ll need member data, categories and custom fields yet.

You see the new masthead element - you could make this dynamic and pull the Channel name etc but I chose to just put static text there.

Possible Nesting Issue
One issue I just noted is that the EE Docs indicate the tags that will return comments for an entry shouldn’t be nested inside a channel:entries loop. If that ends up affecting us here we’ll have to re-arrange our code a bit but let’s see if that becomes an issue before worrying about it. 

Contrary to what you might think in writing these tutorial series I don’t do the whole site first and then go back and write things up - I’m pretty much making it up as I go along. I think this process is close to how most people learn EE so I don’t mind if these types of issues come up and cause a bit of template re-work.

Loading the Correct Entry
So you might be looking at this template and wonder how it will know which entry to load. There is nothing in the parameters of the channel:entries tag that force it to load any certain entry, so it can be a bit mysterious.

The secret lay in how we will link to these single-entry templates. Let’s look at the snp_blog_post snippet that both the above template and blog/index use:

<!-- Standard -->
article class="format-standard">
div class="feature-image">
{if segment_2 !="post"} {!-- only link image on the blog index view --}
<a href="{url_title_path='blog/post'}">
img src="{blog_post_image:main}" alt="{title}" />

        {if segment_2 
== "post"} {!-- no link on single-entry page --}
<img src="{blog_post_image:main}" alt="{title}" />
div class="box cf">
div class="entry-date"><div class="number">{entry_date format="%j"}</div><div class="month">{entry_date format="%M"}</div></div>
div class="excerpt">
{if segment_2 != "post"} {!-- on the blog/index so need links to single-entry and only show summary --}
<a href="{url_title_path='blog/post'}" class="post-heading" >{title}</a>
<p><a href="{url_title_path='blog/post'}" class="learnmore">Learn More</a></p>
            {if segment_2 
=="post"} {!-- on the single entry so don't link and show full text --}
                <div class="post-heading">{title}</div>
                <div class="entry-content">
        <div class="meta">
            <span class="format">Post</span>
            <span class="user">By {author}</a></span>
            <span class="comments">{comment_total} comments</span>
            <span class="tags"><a href="#">red</a>, <a href="#">cyan</a>, <a href="#">white</a>, <a href="#">blue</a></span>
<!-- ENDS  Standard --> 

The secret sauce is this line of code:

<p><a href="{url_title_path='blog/post'}" class="learnmore">Learn More</a></p

By using the url_title_path variable EE will generate a link along these lines:


Now when our above blog/post template loads, it can look to the URL and find the url-title of the correct entry to retrieve. Entry URL titles will always be unique within one channel. If you publish an entry with the same title as an existing entry, EE will add a number to the end of the entry URL title to ensure that uniqueness.

This is where the “dynamic” property of the channel:entries tag is so valuable, and by setting dynamic=“no” you are telling EE to ignore the URL and load whatever entry the rest of the parameters on the channel:entries tag dictate.  In this case we want dynamic=“yes” or unspecified so that our blog/post template can be dynamically reused for every entry in the blog_post channel.

Conditional Magic
You can see the changes to snp_blog_post - I added conditionals that look at the current URL, and if “post” is in the segment_2 position do some different formatting than if “post” isn’t in the URL.  This is what allows this Snippet to now be used on both the blog/index template and blog/post template.

Now that you understand the work involved for one blog entry type, the changes are similar for the others. In summary this chapter requires the following:

Snippets Modified

  • snp_blog_post
  • snp_blog_image
  • snp_blog_audio
  • snp_blog_link
  • snp_blog_video
  • snp_blog_link

Snippets created

  • snp_blog_comments

Templates Created

  • blog/post
  • blog/image
  • blog/audio
  • blog/quote
  • blog/video

Note that Links don’t get a single entry page - they are not a large enough bit of content to worry about comments on, etc. I modified the related Snippet only to remove the ‘comments’ meta line from it.

Next up we’ll tackle comment implementation.



Category Navigation

<< Previous Entry   

Next Entry >>


Previous Comments

Picture of Elliot

by Elliot

Date: Wednesday, December 19th, 2012
Comment: #1

Hi Mike

Just wondered if you might clarify something for me.

I’m not building the free template but I am using your lessons to create a custom design.

I have a range of categories that I would like to use on the site, however allot of them could use the same channels and snippets to display their content.

What I had hoped to do was to use two ‘channels’ set up to accept the correct files and entries. Then use two generic snippets that are dynamically called to display the content in both the single and master blog templates.

I had assumed that when entering content into a channel I could simply select one of the category options and that this would work as a filter for the content.

In principle its working and does filter the results when calling the category from my page menu…

… The problem is that inside my snippets I am calling the {category_name} to display the appropriate category with the content. When I call content that is in the same channel but has different categories assigned, the {category_name} becomes a list of all the categories used in that channel.

e.g. The channel is: blog_post and within the content entrys I have selected ‘website’ for one category and ‘blog’ for another. This causes my snippet to display ‘websiteblog’ even if it correctly filters the rest of the displayed content.

I think the problem could be caused by calling the Category Tags from within my snippet as everything else works fine.

Can you offer any tips? Or will I have to create channels that match the categories and effectively negate the use of being able to select a category in the publish window from within a master channel.

I would ideally like to continue to display the category name next to my posts.



Picture of Boyink

by Boyink

Date: Wednesday, December 19th, 2012
Comment: #2

Hi Elliot -

I’m not sure I completely follow - but if it’s just a matter of displaying the category that an entry is assigned to from within a channel:entries loop then you want to use the {categories}{/categories} looping pair for the channel:entries tag rather than the standalone categories tag.

Picture of Elliot

by Elliot

Date: Wednesday, December 19th, 2012
Comment: #3

Aha! I’m such an amateur… I spent a day reading documentation, searching with google and scratching my head and there you have it!

I knew it had to be simple, just shows I need to become more fluent with regard to the tags available – in my defence I looked on EE and must have just not seen it or confused the tags with the standalone ones.

Thank you!

Picture of Boyink

by Boyink

Date: Wednesday, December 19th, 2012
Comment: #4

Sure - glad to help.

Picture of Steven

by Steven

Date: Wednesday, February 13th, 2013
Comment: #5


i was wondering when you finish the EE 2 book with the 2.5.5 update? I want to read it!


Mike Boyink

by Mike Boyink (Author)

Date: Thursday, February 14th, 2013
Comment: #6

No date. I’m working on it but with everything else going on it’ll be done when it’s done..;)

Add Your Comment

Commenting is not available in this channel entry.

Unless otherwise stated all content is © Michael Boyink of Train-ee.com & Boyink Interactive. Please don't steal - I've got kids to feed...