WordPress Custom Fields in Comments
I’ve been tinkering with how to add custom fields to my wordpress comments. It turns out the documentation is sort of sparse in regards to doing so, but a few helpful posts, and some digging inside of the comment-template.php core file finally got me there.
The Background
I’ve got regular posts and such with regular comments. I’ve got a custom post type set up for a section of a site thats called “units”. I wanted this custom post type to have it’s own special comments with the additional custom fields (It could be star ratings, drop down menus, extra input fields, whatever.) I wanted regular comments everywhere on the site, except comments that were of that ‘unit’ post type. Since WordPress 3.0, there is a new generic form for handling comments. In specific, this function call ‘comment_form()’ loads it up. This tutorial assumes your working with something later than 3.0 and using this new method of calling and formatting comments…
The Solution
Step: 1
The first thing is we have to set up a new comment.php template file, which we will include in our single.php post type pages. The easiest way to do this, is just make a copy the comments.php and rename it comments-units.php. That way we can have the two separate comment template files, and load them wherever we choose.
Find your ‘single-units.php’ file, (or whatever template file you want to add your new comments to, and change this:
1 |
comments_template( '/comments.php', true ); |
To this:
1 |
comments_template( '/comments-units.php', true ); |
The ‘true’ second parameter makes WordPress sort ‘trackback’ comments separately from ‘regular’ comments
Step: 2
Open up your comments-units.php file and find this line of code (near the bottom)
1 |
<?php comment_form(); ?> |
Replace that comment_form line, with the following bit of code. Of course, customize for your own needs.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php $args = array( 'id_form' => 'commentform', 'id_submit' => 'submit', 'title_reply' => __( 'Leave a Unit Report' ), 'title_reply_to' => __( 'Leave a Reply to %s' ), 'cancel_reply_link' => __( 'Cancel reply' ), 'label_submit' => __( 'Post Report' ), 'comment_field' => '<p class="comment-form-comment">' . '<label for="comment">' . __( 'Unit Report' ) . '</label>' . '<textarea id="comment" name="comment" cols="45" rows="12" tabindex="4" aria-required="true"></textarea>' . '</p>' ); comment_form($args); ?> |
Note: This comment_form() function initiates the comment form. We pass an variable with a set of arguments to ovverride some of the default items of the comment form. For a full list, see the wp codex directory.
Step 3
Now we need to add whatever custom fields we want, to the default “name, url, website” fields.
I’ve got two simple text input fields I’m adding to the comments here. You can add as many or any type of form field.
1 2 3 4 5 6 |
global $mm_extra_fields; $mm_extra_fields = array( 'hidden_field1' => '<input id="type" name="type" type="hidden" value="unit-report" size="30" />', 'field1' => '<p class="comment-form"><label for="species">Species</label><span class="required">*</span><input id="species" name="species" type="text" value="ex: Mule Deer" size="30"></p>', 'field2' => '<p class="comment-form"><label for="terrain">Terrain</label><input id="terrain" name="terrain" type="text" value="ex: High Altitude, Rocky Terrain" size="30" aria-required="true"></p>' ); |
I’ve put my fields inside of a variable called $mm_extra_fields. This variable is an array, with keys and values. The value for each key is the HTML that I will output via wp filters to the default fields list. I’m giving it global scope, so I can use it inside of my hook function below
Here is the hook, that adds the above fields, to the comment form list.
1 2 3 4 5 6 7 8 |
add_filter('comment_form_default_fields','mm_extra_fields'); function mm_extra_fields($fields) { global $mm_extra_fields; foreach($mm_extra_fields as $mm_extra_field_key => $mm_extra_fields_html){ $fields[$mm_extra_field_key] = $mm_extra_fields_html; } return $fields; } |
You can see that we’re just looping over our array via foreach, and adding new keys and values to the the $fields[] variable. Once were done, we return the $fields variable, which has our new fields attached! Wallah. We’re half way there…
You can see the before and after in the following photo. (Don’t stop here, as there are a couple of “gotchas” ahead.)
Step 4
One or two notes. If your using your own CSS or forms, style accordingly. I’ve had to make a few additions to the TwentyEleven css file, to get my new fields to style the same as the other defaults. Namely the paragraph tag, that surrounds the form element. I gave mine the generic class name of 'class="comment-form"'
You’ll need to go add css styles to accommodate for this class name.
For example, you’d need to modify all of the css blocks, that deal with comment form styling to look something like this: (note I added my comment-form selector to the top of the grouped selectors). There are a few other spots you’ll need to do the same…
1 2 3 4 5 6 7 |
#respond .comment-form, #respond .comment-form-author, #respond .comment-form-email, #respond .comment-form-url, #respond .comment-form-comment { position: relative; } |
Step 5
Here’s one of those gotchas. Everything looks fine and dandy so far, but you’d sooner or later (hopefully sooner) realize that IF the user is logged in, all of your custom comment fields go away. Not good. Not good at all.
Luckily there is a relatively easy fix for that. We call upon another hook to add our same fields, if the user is logged in. Here’s the code.
1 2 3 4 5 6 7 |
add_action( 'comment_form_logged_in_after', 'mm_extra_comment_fields_logged_in',10,2); function mm_extra_comment_fields_logged_in($commenter,$user_identity){ global $mm_extra_fields; foreach($mm_extra_fields as $mm_extra_fields_html){ echo $mm_extra_fields_html."\n"; } } |
We’re re-using our array of extra fields we created earlier, and following the same logic on the first filter. We’re just using a different hook this time…
Step 6
Get some ice cream already!
Step 7
Okay, so we have our form, it loads properly both when and when not logged in. Now we just need a couple of more hooks to actually SAVE the form data into the database, and retrieve it to display with our comments… Easy, right?
To save the custom comment fields, we call the function ‘add_comment_meta()’ in the comment_post hook
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
add_action ('comment_post', 'mm_add_comment_meta', 1); function mm_add_comment_meta($comment_id) { if(isset($_POST['type'])){ $type = wp_filter_nohtml_kses($_POST['type']); add_comment_meta($comment_id, 'comment-type', $type, false); } if(isset($_POST['species'])){ $species = wp_filter_nohtml_kses($_POST['species']); add_comment_meta($comment_id, 'species', $species, false); } if(isset($_POST['terrain'])){ $terrain = wp_filter_nohtml_kses($_POST['terrain']); add_comment_meta($comment_id, 'terrain', $terrain, false); } } |
That’s it. Whenever a comment gets posted, it will add our extra fields to the “comments_meta” database table. This works exactly like ‘custom_fields’ for regular posts. It’s all just stored as meta data, but in it’s own comments_meta table. Spiffy. The wp_filter_nohtml_kses function strips out any html tags from the data, so users can’t upload malicious scripts or html… There are several other validation functions in the codex to ensure safe data…
You might have noticed that in the first code drop, I actually had a hidden field called ‘type’ that gets added along with my two visible fields. I’m adding this, so I can flag comments to be my special ‘type’ in the database. This is sort of a hack, and no official documentation on how this should be used, but I’ll show it for completeness sake.
Just like regular posts have a ‘post_type’ field, comments have a “comment_type” field. WordPress only uses 2. If it’s blank, that means it’s a regular comment, if it’s not a regular comment, it might say ‘trackback’. Right now, I think those are the real only use cases.
Since I have my own ‘type’ of comment, I decided to add ‘unit-report’ in that field of the comment being inserted. This allows me to run custom queries on the DB and get all comments that are of type=’unit-report’ should I need. Here’s how.
1 2 3 4 5 6 7 8 9 10 11 12 |
add_filter('preprocess_comment','mm_unit_comment_type'); function mm_unit_comment_type($commentdata){ global $post; if ($post->post_type == 'units' { $commentdata['comment_type'] = 'unit-report'; return $commentdata; } else{ return $commentdata; } } |
First we check to make sure the comment is coming from comments of our custom post type ‘units’, if it is, we add the comment_type of ‘unit-report’. That’s really it.
Step LAST
The lastliest thing we need to do, is display our custom meta values on our comments. This is pretty easy. I imagine most people are using the callback method for displaying posts, which is the way the default themes do it. In order to make this work, you’ll need to go find that callback function call. It looks like this, and should be in the middle of the the template file comments loop. (The function name is twentyeleven_comment)
1 |
wp_list_comments( array( 'callback' => 'twentyeleven_comment' ) ); |
Find that callback function (in your functions.php file) and edit the line that looks like this:
1 2 3 |
<div class="comment-content"> <?php comment_text(); ?> </div> |
I made mine look like this. (We simply use a function called ‘get_comment_meta’, which takes the comment id, and key-name.) Setting the third parameter to true makes it output a string, if set to false, it will return an array
1 2 3 4 5 6 7 8 9 10 11 12 |
<div class="comment-content"> <?php if(is_singular('units')){ ?> <p><?php echo "Species: ".get_comment_meta( $comment->comment_ID, 'species', true ); ?></p> <p><?php echo "Terrain: ".get_comment_meta( $comment->comment_ID, 'terrain', true ); ?></p> <span>Unit Report:</span> <?php } ?> <?php comment_text(); ?> </div> |
Now we’re really done. I do a quick check to see if we’re on a comment page of my post type of ‘units’ (because both regular comments and my special ‘unit comments use this same callback for display) if so, we display the extra fields from the database we added earlier! Phew. That was lot.
Comment and ask questions, or suggest better/alternate ways of noodling. If you’ve made it this far, congrats. There is admittingly ONE thing missing. Now way to “edit” the custom wordpress comment fields on the back-end, like you can with regular comments. Maybe I’ll look into this later…
Style to taste!
Category: General
Joaninha
July 19, 2011 - 11:47 am
I’m implementing this on one of my blogs right now, the tut you created is plain simple to understand.
You have no idea for how long i’ve been dying for a solution like this…
Just a tip: create a nice plugin and just sell it, you deserve the credit and to be rewarded for this
Ballyhoo Blog
July 20, 2011 - 2:17 pm
Glad I could help you out. The tutorial has one update which is VERY important.. Sanitizing the new comment fields so that malicious code cannot be added with a comment… Check step 7 for the updates
Joaninha
August 2, 2011 - 4:12 pm
That sure is important, you never know what users might type into those fields.
Thanks again
Jake
August 31, 2011 - 7:27 pm
Hi,
I am able to get the fields to show up in my comment form, but after I do a test comment and click “post”, the information gets lost. Would you mind sending me an email so I can send you my comment-template.php file? Maybe you can tell me what I’m doing wrong. If so, I would really appreciate it.
Ballyhoo Blog
September 4, 2011 - 3:54 pm
I”m not sure. It could be the fact that I have a if(is_singular(‘units’)) line in there. Change that to ‘posts’ or some other custom post type…
Faye
September 1, 2011 - 3:52 am
Great tutorial but I think I’m having the same issue as Jake above! Have followed the tutorial to the letter, all seems fine, except when I post a test comment, the content of the custom meta fields doesn’t display (I just get the echoed Species: and Terrain: but not the info I entered in those custom boxes). Any suggestions?
Ballyhoo Blog
September 4, 2011 - 3:55 pm
Are you using twentyeleven theme?
Pierre Wiberg
September 19, 2011 - 4:41 pm
Hi
Great tutorial!
I’m using it a custom comment field for a link, is it posible to make that link active?
If the field is left empty from the user empty I dont want anything to be printed in the comment in front end.
I was wondering how to add html tags where you echo the field
eg. echo get_comment_meta( $comment->comment_ID, ‘link’, true );
I just dont know how to get this done.
Any help would be awesome!
THANKS!!
Ballyhoo Blog
September 20, 2011 - 1:28 pm
You’d have to add html link tags.
Something like (not tested)
Riel
October 3, 2011 - 8:34 am
Hello!
I am having the same issues, that the extra fields are not written to the database and get lost.
I do not know what is going wrong, for testing purposes I changed
if(isset($_POST[‘terrain’])){
$terrain = wp_filter_nohtml_kses($_POST[‘terrain’]);
add_comment_meta($comment_id, ‘terrain’, $terrain, false);
to just
$terrain = “Test text”;
add_comment_meta($comment_id, ‘terrain’, $terrain, false);
to force the add_comment_meta, but it also is not showing up, nor it is entered in the database (in phpmyadmin).
I am using WP 3.2.1
Lai Shao Yi
December 5, 2011 - 5:08 pm
really helpful.
thank you.
cashinghub
January 15, 2012 - 2:33 pm
Great post and A great information for new blogger.I am still having problem with the customizing comment box. It is very wide and looks too big as compare to the post.
Isabelle
January 31, 2012 - 2:45 am
Hi what a great tutorial.
I’m not able to succeed the 3rd step. My extra fields don’t show up in the form… :-/
Where do I have to write $mm_extra_fields; ? In my function.php file or in comments-unit.php file ?
Thank’s for your help !
I’m using the latest wordpress version and twentyeleven theme.
Fred
February 10, 2012 - 4:57 pm
Even though you made this post some months ago this needs to be said. It’s people like you which make the community what it is.
Thanks for sharing your findings and expertise!
Konsult
February 21, 2012 - 10:46 am
Very rapidly this website will be famous among all blogging people, due to it’s good articles or reviews
Nathalia
February 23, 2012 - 7:01 am
it’s possible to add the extra fields to the email post notification ?
Thanks
Ballyhoo Blog
March 5, 2012 - 11:46 am
It is, but it takes a bit of hacky-esh code. I did it once upon a time, but haven’t revisited this in a while, so something may have changed in thew new WP versions…
BK
March 11, 2012 - 9:33 pm
This is just what I’ve been searching for. Thank you for putting this together.
How would you set up radio inputs?
web designing
March 12, 2012 - 4:23 am
Formatting the look of comment form may give you a distinct look than rivals, even some of website prefer to give more option such comments through open ID, Facebook login and much more which facilitates end users to leave some thing informative in terms of comments.
bluantinoo
March 21, 2012 - 1:05 pm
Very nice tut, it’s been worth my 3 hours searching on this issue :))
There’s just one thing That I could not figure out: is there a way to show custom fields in comments form right AFTER the comment textarea but before the “submit” button?
(I would like to add attachments, and I do not like that to be before textarea)
Dhaval
September 14, 2012 - 10:49 pm
where is the put step 3 4 and 5 in which place and which file pls explain me detail
Interior Designer
April 10, 2013 - 3:08 am
this is the good and great stuff
Brenda
August 20, 2013 - 12:57 pm
great stuff