Sep
30
2009

Custom Template for Single Posts in WordPress


WordPressIf 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:

catid

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?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('&laquo; %link') ?></div>
<div><?php next_post_link('%link &raquo;') ?></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 &raquo;</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:

1
2
3
4
5
6
<?php
if(in_category(32)) {
// Custom Template for Single Posts in Category 32
include 'single-32.php';
} else {
?>

On line #1 and:

74
<?php } ?>

All the way at the bottom.

So now your single.php file should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<?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('&laquo; %link') ?></div>
<div><?php next_post_link('%link &raquo;') ?></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 &raquo;</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().

If you liked this, please share it.

Tags: , , , , , , , , , , , , , , , , , , , , , , , , , , ,

Short URL: http://bit.ly/9dsSkX

Discussion 12 Comments

  1. Gahlord on October 2, 2009 at 9:31 am

    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?

    • c.bavota on October 5, 2009 at 11:56 am

      Not at all.

  2. Karar.A. on October 2, 2009 at 10:33 am

    Wow! very good and useful . Thank you so much.
    best regards

    Karar!

  3. Mary Anne on October 8, 2009 at 7:46 am

    Hi! I’m new to blogging and found your page by “serendipity!” Will doing this help to increase PR?

    • c.bavota on October 13, 2009 at 12:27 pm

      By “doing this” do you mean adding a comment to my site or creating a template for a single post?

  4. Antonio Madonna on October 17, 2009 at 9:07 am

    You can avoid to modify the footer using a code like this:

  5. Antonio Madonna on October 17, 2009 at 9:08 am

    I can’t get my code to show up in the comment…

    • c.bavota on October 21, 2009 at 11:25 am

      Surround it with the <pre lang=”php”> </pre> tags

  6. Slob Jones on November 14, 2009 at 11:53 pm
    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().

    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.

    • c.bavota on November 15, 2009 at 2:36 pm

      is_post() does not exist. is_page() works for both posts and pages. That is just how it is.

  7. Andr?© Valongueiro on January 6, 2010 at 8:44 am

    Perfect, guy! Thank you so much. Really very useful!

    Best wishes!

  8. Avangelist on August 11, 2010 at 3:48 pm

    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.

Leave a Reply

Your email address will not be published. Required fields are marked *

*


To enter code in the comment box, please place it between <pre lang="php"> </pre> tags. You don't have to convert any characters to their hex/HTML code. Just add your code the way you would to any code editor.