WordPress seems to be everywhere these days, and it's no wonder with it's ease of use and ease of customization. In this tutorial, I'll be dissecting the default WordPress theme's comments.php structure and giving you various snippets of code to make your skinning easier.
For your reference, I've also included a small table of contents.
1. The PHP Backend
1 |
<?php if(!empty($_SERVER['SCRIPT_FILENAME']) && 'comments.php' == basename($_SERVER['SCRIPT_FILENAME'])) : ?> |
2 |
<?php endif; ?> |
3 |
|
4 |
<?php if(!empty($post->post_password)) : ?> |
5 |
<?php if($_COOKIE['wp-postpass_' . COOKIEHASH] != $post->post_password) : ?> |
6 |
<?php endif; ?> |
7 |
<?php endif; ?> |
8 |
|
9 |
<?php if($comments) : ?> |
10 |
<?php foreach($comments as $comment) : ?> |
11 |
<?php if ($comment->comment_approved == '0') : ?> |
12 |
<?php endif; ?> |
13 |
<?php endforeach; ?> |
14 |
<?php else : ?> |
15 |
<?php endif; ?> |
16 |
|
17 |
<?php if(comments_open()) : ?> |
18 |
<?php if(get_option('comment_registration') && !$user_ID) : ?> |
19 |
<?php else : ?> |
20 |
<?php if($user_ID) : ?> |
21 |
<?php else : ?> |
22 |
<?php endif; ?> |
23 |
<?php endif; ?> |
24 |
<?php else : ?> |
25 |
<?php endif; ?> |
26 |
This is the raw PHP code that makes your comments.php file function. To a novice, this might look intimidating. However, do not worry: with this tutorial everything in your comments file will become crystal clear!
2. General Code
Preventing direct access to comments.php
1 |
<?php if(!empty($_SERVER['SCRIPT_FILENAME']) && 'comments.php' == basename($_SERVER['SCRIPT_FILENAME'])) : ?> |
2 |
<?php endif; ?> |
This line of code prevents users from viewing comments.php by accident. This page is meant to be included in a post page, not separately. You could consider this a security measure. Inside the statement, you could insert any message you'd want to be displayed to the person viewing the comments.php file, preferably a die
statement.
1 |
<?php if(!empty($_SERVER['SCRIPT_FILENAME']) && 'comments.php' == basename($_SERVER['SCRIPT_FILENAME'])) : ?> |
2 |
<?php die('You can not access this page directly!'); ?> |
3 |
<?php endif; ?> |
Is a password required?
1 |
<?php if(!empty($post->post_password)) : ?> |
2 |
<?php if($_COOKIE['wp-postpass_' . COOKIEHASH] != $post->post_password) : ?> |
3 |
<?php endif; ?> |
4 |
<?php endif; ?> |
This statement (well, 2 actually, but it makes more sense if you view them as one) checks whether a password is required to view the post. Obviously, if you don't have the password to view the post, you're also not allowed to view the comments.
The first if
checks whether there is a password set. The second if
statement checks whether there is a cookie with a password in place and displays the according message when it's not there. You can customize the error message by placing whatever you choose inside the second if
statement.
3. Displaying The Comments
1 |
<?php if($comments): ?> |
2 |
<?php foreach ($comments as $comment) : ?> |
3 |
<?php if ($comment->comment_approved == '0') : ?> |
4 |
<?php endif; ?> |
5 |
<?php endforeach; ?> |
6 |
<?php else : ?> |
7 |
<?php endif; ?> |
This first conditional statement (if($comments)
) checks if there are comments and then loops through them with a foreach
statement. Inside the foreach
statement, you'll notice the following conditional statement: if($comment->comment_approved == '0')
. This checks if the comment has been approved, and shows a message if it's not yet approved.
An example of this would be the following piece of code.
1 |
<?php if($comments) : ?> |
2 |
<ol> |
3 |
<?php foreach($comments as $comment) : ?> |
4 |
<li> |
5 |
<?php if($comment->comment_approved == '0') : ?> |
6 |
<p>Your comment is awaiting approval</p> |
7 |
<?php endif; ?> |
8 |
<p>Your comment</p> |
9 |
</li> |
10 |
<?php endforeach; ?> |
11 |
</ol> |
12 |
<?php else : ?> |
13 |
<p>No comments</p> |
14 |
<?php endif; ?> |
Basic comment template tags
To make this a functional piece of code, you'll need to use the template tags WordPress provides.
Template Tag | Description |
---|---|
<?php comment_ID(); ?> |
the ID of a comment |
<?php comment_author(); ?> |
the author of a comment |
<?php comment_author_link(); ?> |
the author of a comment, wrapped with a link to his website if he specified one |
<?php comment_type(); ?> |
the type of comment; pingback, trackback or a comment |
<?php comment_text(); ?> |
the actual comment |
<?php comment_date(); ?> |
the date it was posted |
<?php comment_time(); ?> |
the time it was posted |
The final result
1 |
<?php if($comments) : ?> |
2 |
<ol> |
3 |
<?php foreach($comments as $comment) : ?> |
4 |
<li id="comment-<?php comment_ID(); ?>"> |
5 |
<?php if ($comment->comment_approved == '0') : ?> |
6 |
<p>Your comment is awaiting approval</p> |
7 |
<?php endif; ?> |
8 |
<?php comment_text(); ?> |
9 |
<cite><?php comment_type(); ?> by <?php comment_author_link(); ?> on <?php comment_date(); ?> at <?php comment_time(); ?></cite> |
10 |
</li> |
11 |
<?php endforeach; ?> |
12 |
</ol> |
13 |
<?php else : ?> |
14 |
<p>No comments yet</p> |
15 |
<?php endif; ?> |
Inserting this into comments.php would give you a ordered list with the comments and the required information or display a message stating that there aren't any comments.
4. The Comment Form
Are you still following me? Good! We're almost there. We just need to process that comment form... Okay, maybe I lied about almost being there. The comment form is actually one of the harder parts of the entire comments.php skin file.
You'll be bombarded with several conditional statements (is a login required, are you logged in, ...). This part is where most starting skinners have the most trouble: misplacing form elements could prevent the form from working at all, without giving a specific PHP error.
To give you an insight into the conditional statements that are involved in the comment form, I'll first be explaining those statements, and include the HTML later on explaining why it should be where it is.
Conditional statement overview
1 |
<?php if(comments_open()) : ?> |
2 |
<?php if(get_option('comment_registration') && !$user_ID) : ?> |
3 |
<?php else : ?> |
4 |
<?php if($user_ID) : ?> |
5 |
<?php else : ?> |
6 |
<?php endif; ?> |
7 |
<?php endif; ?> |
8 |
<?php else : ?> |
9 |
<?php endif; ?> |
The first conditional statement you encounter is <?php if(comments_open()) : ?>
. This basically checks if the comments are open. Obviously, if the comments are closed, you can't post a comment and the comment form is not needed. You can put the message you want to be displayed if the comments are closed between the last <?php else : ?>
and
<?php endif; ?>
.
The second conditional statement (<?php if(get_option('comment_registration') && !$user_ID) : ?>
) checks whether you need to be registred to post a comment and if you are logged in. If the conditional statement is fulfilled, the script should display a link to a place where users can log in. If registration is not required or you are already logged in, the script will continue with the else
part and display the form.
Our final conditional statement then checks if you are logged in or not. Obviously, if you're already logged in it's useless to make you fill in your name, email and website again.
Inserting the form
Congratulations, we've plowed through all of the conditional statements in the comments.php file. Now, all that is left is to add the form in there.
The first thing I can hear you think is: where the hell is that form going to start? Well, you just have to follow common sense. The second conditional statement checks whether you have to be logged in or not, therefor you'd have to display no form until after this statement. Thus the entire form is located inside this conditional statement.
1 |
|
2 |
<?php if(comments_open()) : ?> |
3 |
<?php if(get_option('comment_registration') && !$user_ID) : ?> |
4 |
<p>You must be <a href="<?php echo get_option('siteurl'); ?>/wp-login.php?redirect_to=<?php echo urlencode(get_permalink()); ?>">logged in</a> to post a comment.</p><?php else : ?> |
5 |
<form action="<?php echo get_option('siteurl'); ?>/wp-comments-post.php" method="post" id="commentform"> |
6 |
<?php if($user_ID) : ?> |
7 |
<?php else : ?> |
8 |
<?php endif; ?> |
9 |
</form> |
10 |
<?php endif; ?> |
11 |
<?php else : ?> |
12 |
<p>The comments are closed.</p> |
13 |
<?php endif; ?> |
I've also thrown in the link to the login page, just as I found it in the default comments.php. As I said before, the last conditional statement checks whether you're logged in or not. Obviously, the name, email and website input fields are only displayed if you're not logged in. Let's throw them in there!
1 |
|
2 |
<?php if(comments_open()) : ?> |
3 |
<?php if(get_option('comment_registration') && !$user_ID) : ?> |
4 |
<p>You must be <a href="<?php echo get_option('siteurl'); ?>/wp-login.php?redirect_to=<?php echo urlencode(get_permalink()); ?>">logged in</a> to post a comment.</p><?php else : ?> |
5 |
<form action="<?php echo get_option('siteurl'); ?>/wp-comments-post.php" method="post" id="commentform"> |
6 |
<?php if($user_ID) : ?> |
7 |
<p>Logged in as <a href="<?php echo get_option('siteurl'); ?>/wp-admin/profile.php"><?php echo $user_identity; ?></a>. <a href="<?php echo get_option('siteurl'); ?>/wp-login.php?action=logout" title="Log out of this account">Log out »</a></p> |
8 |
<?php else : ?> |
9 |
<p><input type="text" name="author" id="author" value="<?php echo $comment_author; ?>" size="22" tabindex="1" /> |
10 |
<label for="author"><small>Name <?php if($req) echo "(required)"; ?></small></label></p> |
11 |
<p><input type="text" name="email" id="email" value="<?php echo $comment_author_email; ?>" size="22" tabindex="2" /> |
12 |
<label for="email"><small>Mail (will not be published) <?php if($req) echo "(required)"; ?></small></label></p> |
13 |
<p><input type="text" name="url" id="url" value="<?php echo $comment_author_url; ?>" size="22" tabindex="3" /> |
14 |
<label for="url"><small>Website</small></label></p> |
15 |
<?php endif; ?> |
16 |
</form> |
17 |
<?php endif; ?> |
18 |
<?php else : ?> |
19 |
<p>The comments are closed.</p> |
20 |
<?php endif; ?> |
Alright! We're almost there! We just need to add in some simple lines of code such as a textarea and a submit button. These go after the last conditional statement, since it's irrelevant for these elements if you are logged in or not.
1 |
<?php if(comments_open()) : ?> |
2 |
<?php if(get_option('comment_registration') && !$user_ID) : ?> |
3 |
<p>You must be <a href="<?php echo get_option('siteurl'); ?>/wp-login.php?redirect_to=<?php echo urlencode(get_permalink()); ?>">logged in</a> to post a comment.</p><?php else : ?> |
4 |
<form action="<?php echo get_option('siteurl'); ?>/wp-comments-post.php" method="post" id="commentform"> |
5 |
<?php if($user_ID) : ?> |
6 |
<p>Logged in as <a href="<?php echo get_option('siteurl'); ?>/wp-admin/profile.php"><?php echo $user_identity; ?></a>. <a href="<?php echo get_option('siteurl'); ?>/wp-login.php?action=logout" title="Log out of this account">Log out »</a></p> |
7 |
<?php else : ?> |
8 |
<p><input type="text" name="author" id="author" value="<?php echo $comment_author; ?>" size="22" tabindex="1" /> |
9 |
<label for="author"><small>Name <?php if($req) echo "(required)"; ?></small></label></p> |
10 |
<p><input type="text" name="email" id="email" value="<?php echo $comment_author_email; ?>" size="22" tabindex="2" /> |
11 |
<label for="email"><small>Mail (will not be published) <?php if($req) echo "(required)"; ?></small></label></p> |
12 |
<p><input type="text" name="url" id="url" value="<?php echo $comment_author_url; ?>" size="22" tabindex="3" /> |
13 |
<label for="url"><small>Website</small></label></p> |
14 |
<?php endif; ?> |
15 |
<p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p> |
16 |
<p><input name="submit" type="submit" id="submit" tabindex="5" value="Submit Comment" /> |
17 |
<input type="hidden" name="comment_post_ID" value="<?php echo $id; ?>" /></p> |
18 |
<?php do_action('comment_form', $post->ID); ?> |
19 |
</form> |
20 |
<?php endif; ?> |
21 |
<?php else : ?> |
22 |
<p>The comments are closed.</p> |
23 |
<?php endif; ?> |
This code should be pretty self-explanatory. A textarea field for the comment, a submit button, a hidden input field with the comments' future ID and a PHP snippet (<?php do_action('comment_form', $post->ID); ?>
) WordPress requires to make the comment form function.
Voila! That's all folks! You've now got your fully ready comments.php file. View this file to get all the PHP and HTML code that is required. You should end up with this (I simply replaced the default skin's comments.php file with ours and added some minor styling to it.)



5. Some Little Tricks
Of course, you now only have a basic comments.php file. There's tons of things you could do to further improve it. I'll list some little tips and tricks to help you on your way.
Gravatars
As of WordPress 2.5, there is a custom WordPress template tag to embed gravatars. It pulls the gravatar from the email the visitor entered. The code to do this is very simple.
1 |
<?php echo get_avatar($author_email, $size, $default_avatar ); ?> |
You can replace $author_email
with the nifty get_comment_author_email();
function, $size
is the height (and width) of the avatar and $default_avatar
is a link to the default avatar image (displayed when the commenter has no gravatar).
Insert this code inside the foreach
loop that displays the comments. The output is a image with the classes avatar
and avatar-$size
(where $size
is the size you specified). With some minor CSS editing, you could end up with something like this:



Comment numbers
I purposely left out headers in the comments.php file we created later, since I believed they would make for excess code in a learning process that's difficult enough as it is. Obviously, I'm not forgetting them though.
Usually, people have a heading displaying something similar to "3 comments so far". This is really easy to achieve thanks to the template tags WordPress offers.
1 |
<?php comments_number($zero_comments, $one_comment, $more_comments); ?> |
It's pretty self-explanatory: $zero_comments
is the text to display when there are no comments, $one_comment
when there is one comment and $more_comments
when there are multiple comments. A real life example would be like this:
1 |
<?php comments_number('No comments', 'One comment', '% comments'); ?> |
I used %
for multiple comments, since the comments_number
function then replaces the %
with the number of comments (2, 3, …)
Used in our comments.php file, you'll end up with something like this:



Comment links
To display a link to the comments part (with the number of comments displaying aswell), you simply use the following code.
1 |
<?php comments_popup_link($zero_comments, $one_comment, $more_comments, $css_class, $comments_closed); ?> |
The first 3 parameters in this function are the same as the above comments_number
function. $css_class
is, obviously, the css class that you give to the <a>
tag and $comments_closed
is the text that should be displayed when the comments are closed. When applying this to a theme, this is a possible way to use it.
1 |
<?php comments_popup_link('No comments', 'One comment', '% comments', 'comments-link', 'Comments are closed'); ?> |
This would then give you a link with the class comments-link
Editing comments
Sometimes you'll want to immediately edit a comment. Luckily, with the edit_comment_link function, you can easily go to the right page to edit it, instead of having to browse to your admin panel to finally reach that comment. Usage is as such:
1 |
<?php edit_comment_link($link_text, $before_link, $after_link); ?> |
You have to put this inside the foreach
comment loop. Parameters are quite obvious: $link_text
is the anchor text for the edit link, $before_link
and $after_link
respectively are the text or code to display before or after the link.
This really makes it easy to change a comment; you could simply add a small 'Edit' link to your comment meta information (only viewable by the admin). This is what it could look like:



Alternating colors for comments
It's possible that you'd want to have alternating row colors for your comments, to make a clearer separation. Doing this is relatively easy. First, add the following code to the top of the page:
1 |
function alternate_rows($i){ if($i % 2) { echo ' class="alt"'; } else { echo ''; } |
2 |
} |
Then add the following inside the foreach
loop (again). You could simply replace <li id="comment-<?php comment_ID(); ?>">
with this:
1 |
<?php $i++; ?> |
2 |
<li<?php alternate_rows($i); ?> id="comment-<?php comment_ID(); ?>"> |
This will give every other comment the class alt
, thus making it possible to change their appearance through CSS.
I decided to make a function for it, to have less clutter in your actual theme file. You could add the function definition into your functions.php file if you'd like to, but it makes more sense, to me, to have it at the top of your page.
Alternating rows make it easier to distinguish different comments; once implemented you might have something like this:



Displaying the allowed tags
To display the code that visitors are allowed to use in their comments, simply use this little snippet.
1 |
Allowed tags: <?php echo allowed_tags(); ?> |
Then you'll simply get a list of the tags that are allowed in your comments, like this:
Comments RSS link
To get a link to the RSS feed for the comments of a certain post, simply insert the code below into your comments.php file on the place where you want it to be.
1 |
<?php comments_rss_link($link_text); ?> |
Then simply replace $link_test
with the anchor text for the RSS link.
This can come in handy if you want to give your visitors the opportunity to subscribe to the comment feed for a specific article or blog post. You could implement it like this:



6. Conclusion
I hope you've enjoyed this *ahem* little article about skinning your WordPress comments.php file. You can get the full code here, with the tricks I showed included in it:
- gravatars,
- alternate row colors,
- edit link,
- comments rss link.
Obviously, the comments link isn't included since this has to be used inside of the loop.
Best of luck in your WordPress skinning adventures!