Custom Template for Single Posts in WordPress
by c.bavota | Posted in Tutorials | 22 comments
If you take a look at the template hierarchy in WordPress, you will notice that you have the ability to create custom templates for different category pages by simply adding the category slug or id to the end of your filename. So category-articles.php will be called before category.php if you query the Articles category. But what if you wanted to have a custom template for every post in the Articles category so that it displayed differently from posts in other categories. By default that can’t be done unless you do a little hacking.
Here is an easy way to create custom templates for single posts in WordPress.
First, we need to figure out the category id of the posts we want to customize. Open up your wp-admin and go to the Categories page. Click on the category you want and then take a look in the address bar. You should see something like this:
The 32 at the end is your category id.
Now open up your single.php file and let’s make a few changes. I will use the single.php file from the Default theme as an example.
<?php
/**
* @package WordPress
* @subpackage Default_Theme
*/
get_header();
?>
<div id="content" role="main">
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<div>
<div><?php previous_post_link('« %link') ?></div>
<div><?php next_post_link('%link »') ?></div>
</div>
<div <?php post_class() ?> id="post-<?php the_ID(); ?>">
<h2><?php the_title(); ?></h2>
<div>
<?php the_content('<p>Read the rest of this entry »</p>'); ?>
<?php wp_link_pages(array('before' => '<p><strong>Pages:</strong> ', 'after' => '</p>', 'next_or_number' => 'number')); ?>
<?php the_tags( '<p>Tags: ', ', ', '</p>'); ?>
<p>
<small>
This entry was posted
<?php /* This is commented, because it requires a little adjusting sometimes.
You'll need to download this plugin, and follow the instructions:
http://binarybonsai.com/wordpress/time-since/ */
/* $entry_datetime = abs(strtotime($post->post_date) - (60*120)); echo time_since($entry_datetime); echo ' ago'; */ ?>
on <?php the_time('l, F jS, Y') ?> at <?php the_time() ?>
and is filed under <?php the_category(', ') ?>.
You can follow any responses to this entry through the <?php post_comments_feed_link('RSS 2.0'); ?> feed.
<?php if ( comments_open() && pings_open() ) {
// Both Comments and Pings are open ?>
You can <a href="#respond">leave a response</a>, or <a href="<?php trackback_url(); ?>" rel="trackback">trackback</a> from your own site.
<?php } elseif ( !comments_open() && pings_open() ) {
// Only Pings are Open ?>
Responses are currently closed, but you can <a href="<?php trackback_url(); ?> " rel="trackback">trackback</a> from your own site.
<?php } elseif ( comments_open() && !pings_open() ) {
// Comments are open, Pings are not ?>
You can skip to the end and leave a response. Pinging is currently not allowed.
<?php } elseif ( !comments_open() && !pings_open() ) {
// Neither Comments, nor Pings are open ?>
Both comments and pings are currently closed.
<?php } edit_post_link('Edit this entry','','.'); ?>
</small>
</p>
</div>
</div>
<?php comments_template(); ?>
<?php endwhile; else: ?>
<p>Sorry, no posts matched your criteria.</p>
<?php endif; ?>
</div>
<?php get_footer(); ?>
To get this little hack to work all you need to do is add:
<?php
if(in_category(32)) {
// Custom Template for Single Posts in Category 32
include 'single-32.php';
} else {
?>
On line #1 and:
All the way at the bottom.
So now your single.php file should look like this:
<?php
if(in_category(32)) {
include 'single-32.php';
} else {
?>
<?php
/**
* @package WordPress
* @subpackage Default_Theme
*/
get_header();
?>
<div id="content" role="main">
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<div>
<div><?php previous_post_link('« %link') ?></div>
<div><?php next_post_link('%link »') ?></div>
</div>
<div <?php post_class() ?> id="post-<?php the_ID(); ?>">
<h2><?php the_title(); ?></h2>
<div>
<?php the_content('<p>Read the rest of this entry »</p>'); ?>
<?php wp_link_pages(array('before' => '<p><strong>Pages:</strong> ', 'after' => '</p>', 'next_or_number' => 'number')); ?>
<?php the_tags( '<p>Tags: ', ', ', '</p>'); ?>
<p>
<small>
This entry was posted
<?php /* This is commented, because it requires a little adjusting sometimes.
You'll need to download this plugin, and follow the instructions:
http://binarybonsai.com/wordpress/time-since/ */
/* $entry_datetime = abs(strtotime($post->post_date) - (60*120)); echo time_since($entry_datetime); echo ' ago'; */ ?>
on <?php the_time('l, F jS, Y') ?> at <?php the_time() ?>
and is filed under <?php the_category(', ') ?>.
You can follow any responses to this entry through the <?php post_comments_feed_link('RSS 2.0'); ?> feed.
<?php if ( comments_open() && pings_open() ) {
// Both Comments and Pings are open ?>
You can <a href="#respond">leave a response</a>, or <a href="<?php trackback_url(); ?>" rel="trackback">trackback</a> from your own site.
<?php } elseif ( !comments_open() && pings_open() ) {
// Only Pings are Open ?>
Responses are currently closed, but you can <a href="<?php trackback_url(); ?> " rel="trackback">trackback</a> from your own site.
<?php } elseif ( comments_open() && !pings_open() ) {
// Comments are open, Pings are not ?>
You can skip to the end and leave a response. Pinging is currently not allowed.
<?php } elseif ( !comments_open() && !pings_open() ) {
// Neither Comments, nor Pings are open ?>
Both comments and pings are currently closed.
<?php } edit_post_link('Edit this entry','','.'); ?>
</small>
</p>
</div>
</div>
<?php comments_template(); ?>
<?php endwhile; else: ?>
<p>Sorry, no posts matched your criteria.</p>
<?php endif; ?>
</div>
<?php get_footer(); ?>
<?php } ?>
Now all you need to do is create a file called single-32.php and add it to your theme. Code that file however you want your single page posts in category 32 to appear and you are done.
You can also use this hack if you want to create a custom template for a specific post. Just replace in_category() with is_page().



Perfect. Thanks so much, needed this info today in fact.
Does making the server check every single post for that category via the script at the top of the single.php have a dramatic impact on site load times or other performance?
Not at all.
Wow! very good and useful . Thank you so much.
best regards
Karar!
Hi! I’m new to blogging and found your page by “serendipity!” Will doing this help to increase PR?
By “doing this” do you mean adding a comment to my site or creating a template for a single post?
You can avoid to modify the footer using a code like this:
I can’t get my code to show up in the comment…
Surround it with the <pre lang=”php”> </pre> tags
I don’t see how this would work. Individual posts are just that – posts. They’re not pages. So how could the tag is_page work with a post?
Is there an is_post tag? That would be more logical.
is_post()does not exist.is_page()works for both posts and pages. That is just how it is.Perfect, guy! Thank you so much. Really very useful!
Best wishes!
I would suggest that the cleaner solution – although still not ideal, would be to completely botch single.php into a page running conditions and calling external files based on types.
Where you have the else statement, I would take all that code, and put it into a master-single file leaving this one to assemble the right page code.
I would say there must be a way of doing this using the functions file and leaving the single.php file untouched entirely.
I’ve been looking around for a solution to single page templates for awhile, and everything I found felt so hacked. Except for this. This is simple, small, and works. Thanks!
Heres my code for custom post template i did for a news website using wordpress as a core.
<?php global $post, $legalnews; $IndividualArray = wp_get_post_categories($post->ID); if (!empty($legalnews['interview']) && in_array($legalnews['interview'], $IndividualArray)) { include TEMPLATEPATH. '/interview.php'; } elseif (!empty($legalnews['photos_id']) && in_array($legalnews['photos_id'], $IndividualArray)) { include TEMPLATEPATH. '/single_photos.php'; } else { include TEMPLATEPATH. '/single.php'; } ?>I thought single posting in WordPress was next to impossible without using hacks! i was really amazed when i read your blog thanks to you i can now do single posting on my blog. Kodus to you!!
Well well well DONE!
Not only the topic is good but all the discussion!!!
congrats to everyone! lol
Hey! Great Article!
What if the element you want to change is not in the single.php file but in the loop.php file? The loop calls the post thumbnail to appear before the post title. But I want, for a specific category, to remove that thumbnail from the loop…
Hopefully I am making myself clear.
Thanks so much for this!
If you are using loop.php you need to take advantage of conditional tags such as
is_category(). Read about it here.http://codex.wordpress.org/Conditional_Tags
Awesome guide this is just what i was looking for, thanks!
THANKS! Very helpful, elegant solution.