WordPress 3.0 Theme Tip: The Comment Form
WordPress 3.0 has something very handy that I want theme authors to start implementing as soon as possible.
To show exactly why it’s so useful, I modified my own theme to start using it.
Demonstration
So, here’s a big hunk of code I pulled out of my current theme’s comments.php. This hunk of code has only one purpose: To display the form area where people can leave a comment:
<?php if ('open' == $post->comment_status) : ?> <div id="respond"> <h3><?php comment_form_title( 'Leave a Reply', 'Leave a Reply to %s' ); ?></h3> <div class="cancel-comment-reply"> <small><?php cancel_comment_reply_link(); ?></small> </div> <?php if ( get_option('comment_registration') && !$user_ID ) : ?> <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 : ?> <form action="<?php echo get_option('siteurl'); ?>/wp-comments-post.php" method="post" id="commentform"> <?php if ( $user_ID ) : ?> <p>Logged in as <a href="<?php echo get_option('siteurl'); ?>/wp-admin/profile.php"><?php echo $user_identity; ?></a>. <a href="<?php echo wp_logout_url(get_permalink()); ?>" title="Log out of this account">Log out »</a></p> <?php else : ?> <p><input type="text" name="author" id="author" value="<?php echo $comment_author; ?>" size="22" tabindex="1" /> <label for="author"><small>Name <?php if ($req) echo "(required)"; ?></small></label></p> <p><input type="text" name="email" id="email" value="<?php echo $comment_author_email; ?>" size="22" tabindex="2" /> <label for="email"><small>Mail (will not be published) <?php if ($req) echo "(required)"; ?></small></label></p> <p><input type="text" name="url" id="url" value="<?php echo $comment_author_url; ?>" size="22" tabindex="3" /> <label for="url"><small>Website</small></label></p> <?php endif; ?> <!--<p><small><strong>XHTML:</strong> You can use these tags: <code><?php echo allowed_tags(); ?></code></small></p>--> <p><textarea name="comment" id="comment" cols="100%" rows="10" tabindex="4"></textarea></p> <p><input name="submit" type="submit" id="submit" tabindex="5" value="Submit Comment" /> <?php comment_id_fields(); ?> </p> <?php do_action('comment_form', $post->ID); ?> </form> <?php endif; // If registration required and not logged in ?> </div> <?php endif; // if you delete this the sky will fall on your head ?>
Nasty, eh? It’s a mess of if/else statements. It handles cases where the user is logged in or not, where the comments are open or closed, whether registration is required, etc. It’s confusing, difficult to modify, poor for CSS referencing…
Here’s what I replaced all that code with:
<?php comment_form(); ?>
Now then, that’s much better, isn’t it?
The comment_form function is new to 3.0. Basically, it standardizes the comments form. It makes it wonderful for us plugin authors, since now we can easily modify the comments form with various hooks and things. I’ve already modified Simple Facebook Connect and Simple Twitter Connect to support this new approach; if you’re using a theme with this, then the user won’t have to modify it to have their buttons appear on the comments form.
Customizing
Since theme authors love to customize things, the comments form is also extremely customizable. Doing it, however, can be slightly confusing.
Inside the comments_form function, we find some useful hooks to let us change things around.
The first hook is comment_form_default_fields. This lets us modify the three main fields: author, email, and website. It’s a filter, so we can change things as they pass through it. The fields are stored in an array which contains the html that is output. So it looks sorta like this:
array( 'author' => '<p class="comment-form-author">...', 'email' => '<p class="comment-form-email">...', 'url' => '<p class="comment-form-url">...' );
I truncated it for simplicity. But what this means is that code like this can modify the fields:
function my_fields($fields) { $fields['new'] = '<p>Some new input field here</p>'; return $fields; } add_filter('comment_form_default_fields','my_fields');
That sort of thing lets us add a new input field, or modify the existing ones, etc…
But fields aren’t the only thing we can change. There’s a comment_form_defaults filter too. It gets a lot of the surrounding text of the comments form. The defaults look sorta like this:
$defaults = array( 'fields' => apply_filters( 'comment_form_default_fields', $fields ), 'comment_field' => '<p class="comment-form-comment">...', 'must_log_in' => '<p class="must-log-in">...', 'logged_in_as' => '<p class="logged-in-as">...', 'comment_notes_before' => '<p class="comment-notes">...', 'comment_notes_after' => '<dl class="form-allowed-tags">...', 'id_form' => 'commentform', 'id_submit' => 'submit', 'title_reply' => __( 'Leave a Reply' ), 'title_reply_to' => __( 'Leave a Reply to %s' ), 'cancel_reply_link' => __( 'Cancel reply' ), 'label_submit' => __( 'Post Comment' ), );
All the various pieces of html that are displayed as part of the comment form section are defined here. So those can be modified as you see fit. However, unlike the fields, adding new bits here won’t help us at all. The fields get looped through for displaying them, these are just settings that get used at various times.
But filters are not the only way to modify these. The comment_form function actually can take an array of arguments as the first parameter, and those arguments will modify the form. So if we wanted a simple change, like to change the wording of “Leave a Reply”, then we could do this:
<?php comment_form(array('title_reply'=>'Leave a Reply, Stupid')); ?>
This gives us a simple and easy way to make changes without all the trouble of filters. Nevertheless, those filters can be very useful for more complex operations.
But wait, there’s more!
As the comments form is being created, there’s a ton of action hooks being called, at every stage. So if you want to insert something into the form itself, there’s easy ways to do it.
A quick list of the action hooks. Most of them are self-explanatory.
- comment_form_before
- comment_form_must_log_in_after
- comment_form_top
- comment_form_logged_in_after
- comment_notes_before
- comment_form_before_fields
- comment_form_field_{$name} (a filter on each and every field, where {$name} is the key name of the field in the array)
- comment_form_after_fields
- comment_form_field_comment (a filter on the “comment_field” default setting, which contains the textarea for the comment)
- comment_form (action hook after the textarea, for backward compatibility mainly)
- comment_form_after
- comment_form_comments_closed
CSS and other extras
Let’s not forget styling. All parts of the comments form have nice classes and id’s and such. Take a look at the resulting HTML source and you’ll find all the styling capabilities you like. Also, everything is properly semantic, using label tags and aria-required and so forth. All the text is run through the translation system for core translations.
So theme authors should start modifying their themes to use this instead of the existing big-ugly-comment-form code. Your users will thank you for it. Plugin authors will thank you for it. And really, it’s about time we made WordPress themes more about design and less about the nuts and bolts of the programming, no?
Ok so I want to use the hook comment_form_before and have it execute some php how do I do that?
Hi! This is okey and I’ve red and understood it from codex, BUT there is some qstn please, how to customize html around submit button? I can change text – okey, but I can’t see where I could paste a piece of code so that my button was stylish. Guys please help me, because my defaulte theme has a tone of codes, I did it all except of that button, really really appriciate for your help
Are you talking about changing the look of the button entirely? if you want to to do that then its best you style it through css.
For example the submit button will have an ‘id’ which will most likely be: id=”submit”; you should then find that id in the css and use the background-image: url() to link to the image you would want your reply button to look like.
I think that should do it, if there is still trouble, shout 🙂
[…] you would like to learn more about customization of the comment form, you might want to check out WordPress 3.0 Theme Tip the Comment Form. Step 10 – Page.php When you create a page in WordPress, a different file is used to display the […]
This is very useful, but I am lost as to what you are meant to do with:
array(
2 ‘author’ => ‘…’,
3 ’email’ => ‘…’,
4 ‘url’ => ‘…’
5 );
Does this array get passed as args? Does this get added into a filter somewhere? I appreciate your post, but it can be very difficult for novices when code snippets get taken out of context….
Thanks
+1 😉
can you explain this a little further? that would be really helpful for people with limited php skills… thanks 🙂
I have removed the “Website” field on my site but still some people commenting with their website .. can anybody tell me how?
@Tushar
They use autometed commenting software (spamming) for posting comments on your website. You may just ignore those comments by marking them as spam.
Hi,
Good help provided by you, but i want to change on my site http://makeadvice.com/ comment looks only, not a field, for me field is ok, just want to change a look, kindly provide some info, for the same, thanks .
Hi thanks for this,
You explain how to add an extra field, but how do you remove one. I don’t want to display the website field.
Thanks 🙂
[…] Otto Share this:Like this:LikeBe the first to like this post. This entry was posted in Code and tagged Comments, WordPress by Nick Hamze. Bookmark the permalink. […]
Also, where does the comment approval function occur (where admins approve or disapprove comments). I’d like to provide additional fields on a comment so that the admin can make adjustments to comments in the admin area, not the actual comment form.
Hi, awesome post.
I’m not a coder, so I was wondering how can I add Google Analytics event tracker to the submit button? I use a twenetyeleven child theme.
I need to add onClick:
Example: <input name="submit" type="submit" id="submit" onClick="_gaq.push(['_trackEvent', 'Forms', 'Submit', 'BlogComments']);" tabindex="5" value="” />
Anyone got any ideas?
Hi Gear,
I have the same problem, I want to add the onclick option in the submit button but I don’t known how to do 🙁
Do you find how to add it?
Albert
Geir E and Albert,
you would add the onclick= to your search form. In twentyeleven you are looking for the file searchform.php.
Copy the searchform.php from your twentyeleven theme folder and paste it into your child theme folder. That way when WordPress update twentyeleven it will update that searchform not your child theme searchform.
Richard
I solved this making a “not smart solution” based on commeting the function comment_form and writing directly the expected html generated code with the onclick information. The only thing that you need is to use the getID(), the_permalink(); and $_SERVER[‘REQUEST_URI’] to complete the dynamic parameters.
Albert.
Thank you very much for sharing this great article. I’m trying to make a wp theme curently. It’s good reference. Thank you.
I would like to remove the log in/ logout text buttons any way to do this?
I have removed the “Website” field on my site but still some people commenting with their website .. can anybody tell me how?
I’m having a really hard time with only one thing…
I have the one line of code in comments.php, and in single.php I have
, but where are the comments actually displayed? I cannot figure this out. I’ve looked in the codex and in tons of forums, but no one else even seems to be having this problem!
Ethan, add this line to your comments.php
above this line
now when you click on the comments links the form will appear..
Oh I forgot, your still going to need to wrap it in a div tag, something like
, that way you will still be able to style the form how you want it. As Otto has mentioned this is not a tutorial people, it pointing out simple changes to a WordPress function. The best way to learn about the comments form is to study the comment form that comes with WordPress Twenty Twelve theme. It’s relatively simple structure makes the form easy to learn.
That should include ….
div id=”comments”
Otto having trouble inserting code!?
If you will read below the comment form, use the [ php ] tags to wrap code for this comment display. That includes HTML tags. If you don’t wrap it in something, your HTML will be wiped out.
ah doh! tried to use regular code, thought that was for php code only..
Thanks a lot it helped me a lot.
[…] $commentdata; } Pour en savoir plus, je vous invite à lire l’article source sur WPEngineer Vous pouvez également lire cet excellent article chez Otto Retour en haut ↑ « [shortcode] Créer une info boxThème WordPress : Les Tags […]
This tutorial sucks… If you’re going to take the time to post a tutorial, don’t “truncate” important details that a visitor will need to implement the design technique… Judging from how many people had to post to try and get clarification on the topic, maybe you should consider revising this so that it makes usable sense.
Firstly, this isn’t a tutorial. It’s just a tip pointing out some of the things that were new to WordPress, 2 years ago. If you need a tutorial on how to use this particular part of the code (which is actually obvious, or should be to anybody messing with this stuff), then you might want to go elsewhere.
Secondly, I didn’t truncate any important details, I highlighted parts that one would need to notice in order to do customization of the comment form. This blog is aimed at people who know how to code already. Given that, if people who don’t know how to code read it and are confused by it, that’s not my target audience and I’m not interested in hold-holding them through the process.
Everybody learns on their own, because there’s no other way to “learn”.
Well it helped me out immensely!
I really don’t know HTML, CSS or any other programming language. Please Help Me Out Here!
Thanks for the tip (and for the good amount of detail put in). I am trying to write a plugin to add a new field to the comments form. I have used hook for “comment_form_default_fields” and added my new field (it is a checkbox). This works fine if no user is logged in. However, if the user is logged on, the form shows with only the comments textarea. Can you tell me what I am doing wrong here (or is it a WP limitation)?
I can’t seem to get my comments.php to work properly. Every time I try leaving a comment I am redirected to a blank page for comments-post.php. Would you have any idea as to how to solve this problem?
@Otto
You are the man! Never knew this function existed until now.
This was GREAT! Thank you, I’ve not been working with WordPress for over a year and am rusty. I didn’t know about the new comment form. Very helpful, I’ll check out the codex and dig into the array. Thanks again.
TFFT !!! I did it!!! Thank you so much, first successful attempt at a hook, nicely led by your article. I can stop banging my head on the wall now 8DDDDDD
[…] This will display a comments form that looks well on our theme, but if you would like to learn more about customization of the comment form, you might want to check out WordPress 3.0 Theme Tip the Comment Form. […]
thank you
I have read this entire post twice at least. I use the Admired theme
I can see where he has the code from you under theme fuctions for comments fields. However,
the comment form is displayed as leave a comment with a comment box. I don’t want to change anything until I am for certain I know exactly what I am doing and I am so confused. Been working on this for two days. I understand your code and the flow but what I see under theme fuctions doesn’t look exactly like yours and I don’t want to change anything. Can you help me. Thanks.
Hi.. i’m working on wordpress blog and i have to implement the same functionality
“Notify me of follow-up comments by email”
“Notify me of new posts by email”
in comments form section as u have implemented in ur form.can you let me know how u have done this ..is there any plugin for that???
please reply..
thanks
The Jetpack plugin adds that functionality.
hey may you tel me how to reset comment form data after submission
Thanks tons for this code. First one I’ve found that actually fully works, and without having to edit or add code to multiple files.
I need a simple comment form like what you have.
I hate Tinymce form in my website.
How I can disable it?
Thank you.
The list for action hook which you provide is really helpful. But i am getting problem for resetting comment form data after submission. Can you help me in that?
This is an excellent post — thank you very much for your help. I was successful changing my comment form and am using Jetpack. I’m wondering, though, how I can change what happens after someone leaves a comment. Right now, it says, “Submitting a comment,” but after that happens, nothing displays. Because I don’t allow automatic comments (unless someone has already had an approved comment), it might be confusing to the commenter that the comment went through. Is there a way to fix this? Thank you very much!
[…] http://ottopress.com/2010/wordpress-3-0-theme-tip-the-comment-form/ […]
if the user is logged on, the form shows with only the comments textarea. Can you tell me what I am doing wrong here (or is it a WP limitation)?
That’s not a limitation, that’s by design. If the user is logged on, then it already knows who they are, so they don’t need to fill out name/email and such.
Hi Otto, thanks for this very thorough explanation. I’m trying to add a required checkbox to the comment form. I am able to add it successfully via the functions.php or in my theme-functions.php (in my woo-theme) however the form still goes through if the checkbox isnt ticked. Only if the name and email arent filled out does pull up the error page.
How can I make the form ensure the field is required before submission.
Good tutorial. Used it to develop my own customized contact form plugin, where I re-define the $args for the comment form fields.
But it turns out, while testing, that some themes create their own ‘textarea’ field, which adds to my ‘textarea’ field, resulting in two comment text fields. Not good.
I have set my add_filter( ‘comment_form_default_fields’, my_function(), 99,1) with a higher priority (99) so that it happens later in the ‘page build’ (after the theme does it’s comment_form_default_fields), but the duplicates comment text boxes are still there. Also tried a priority of 8, and that didn’t do it either.
I also tried unset($arg) (the parameter passed to my_function; contains the array of fields/etc), and a unset($_GLOBAL[$arg]), and still the duplicate textarea field shows up.
So, can you think of a generic (works for any theme) that can determine if the comment field has already been defined? And, if the duplicate is found, remove the one in the theme, so I can replace it with mine? Or is there a better way to ‘start over’ on the defining of fields in the comment form.
I understand that the problem might be caused by bad coding practices on the theme, but would like to find a workaround so a theme doesn’t change the fields I want on the comment form.
Thanks….Rick…
Hi Rick!
Have you solved the duplicating problem? I’ve got the same, with a clean underscores theme and just cannot get rid of the default comment_field box…
Since the ‘duplicating’ problem is theme-based, there are two options: change to another theme, or dig into the theme and re-write the comment function with a custom functions.php in a child theme. (You never want to modify theme code directly, but always use a custom theme.)
I figure if a theme is doing that funny stuff there, then they are probably doing non-standard things elsewhere, so I usually just change themes.
Or you could use add_filter with a lower priority to adjust the $args array to how you need it. Since the lower priority of your function will happen after the theme does it’s non-standard thing, then your changes will ‘stick’. But again, you always need to use a child theme, rather than changing the theme code directly. If you don’t, then your changes disappear during the next theme update.
Heh, found the cause.
In wp-includes/comment-template.php there is a line 2280:
$comment_fields = array( ‘comment’ => $args[‘comment_field’] ) + (array) $args[‘fields’];
So, I’ve just added ‘comment_field’ => ” to the args array passed to comment_form()
…and changing the core code (in comment-temmplate.php) is not a good idea. The next WP update will overwrite your changes.
Child themes and add_filters stuff is safer
I’ve done it not in core code, but in the comments template in my theme. Of course I don’t want modify original code 😉