Adding Custom Fields In WordPress’ Comment Form

Advertisement

If you have created websites or blogs, then you need no introduction to WordPress, one of the most popular content management systems (CMS). WordPress powers millions of websites, for individuals as well as big companies. Why is it so successful?

Apart from its ease of use and the availability of themes and plugins, WordPress can be easily modified to include custom features and functions. Hooks and filters are built into the CMS that allow you to add functionality or strip out something that is not required. You can customize the way WordPress handles content as well as comments. For example, you could require readers to leave their phone number and/or address when leaving a comment.

You might want them to say whether they liked your blog post. You could have any one of thousands of reasons for adding input fields to the comment form on your WordPress website. So, how do you extend the WordPress comment form with a custom input field?

Add custom fields in WordPress comment form1
Flickr/Neal2

In this article, we will add three input fields to the comment form of a WordPress website: two text-input fields (for a phone number and comment title) and a radio option for rating the current article. We will use the add_comment_meta3 function to add a meta data field to comments. In the process, we will also modify the comment form using the comment_form_default_fields filter4 and the comment_form_after_fields and comment_form_logged_in_after actions. And we will use many more functions to achieve the desired result.

We can extend the comment form by editing the theme or by creating a theme that alters the behavior of the active theme to include the additional input fields. Modifying the theme is relatively easier to do, but it has an obvious limitation: all the effort that has gone into customization will be for nought if the theme is replaced. Using a plugin to customize the comment form frees us from this limitation. This way, the customized comment form will apply to all themes (except those that have non-standard methods for adding the comment form). Let’s take the plugin route, to avoid having to go through the entire coding process in case we switch themes. We will call our plugin “Extend Comment.”

Open your text editor of choice (Notepad, Notepad++, BlueFish, etc.), and create a new file, extendcomment.php. Make sure to save it in a folder of the same name, ExtendComment, to keep the organization of files simple. As the first step in our coding, let’s add the headers for our WordPress plugin. The headers are pretty much self-explanatory:

<?php
/*
Plugin Name: Extend Comment
Version: 1.0
Plugin URI: http://smartwebworker.com
Description: A plugin to add fields to the comment form.
Author: Specky Geek
Author URI: http://www.speckygeek.com
*/

Now, we need to start actually adding the input fields. We’ll start by adding a text input field for a phone number. We will add it to the default fields of the comment form for collecting the author’s information. The default fields are for name, email address and website URL. This set of input fields is hidden if the user is logged in. In the code below, we have recalled the information of the logged-in user as well as the information on whether a field is required. We have modified all of the default fields and added a field for a phone number by creating an array with our settings and passing it through a filter.

// Add custom meta (ratings) fields to the default comment form
// Default comment form includes name, email address and website URL
// Default comment form elements are hidden when user is logged in

add_filter('comment_form_default_fields', 'custom_fields');
function custom_fields($fields) {

    $commenter = wp_get_current_commenter();
    $req = get_option( 'require_name_email' );
    $aria_req = ( $req ? " aria-required='true'" : '' );

    $fields[ 'author' ] = '<p class="comment-form-author">'.
      '<label for="author">' . __( 'Name' ) . '</label>'.
      ( $req ? '<span class="required">*</span>' : '' ).
      '<input id="author" name="author" type="text" value="'. esc_attr( $commenter['comment_author'] ) .
      '" size="30" tabindex="1"' . $aria_req . ' /></p>';

    $fields[ 'email' ] = '<p class="comment-form-email">'.
      '<label for="email">' . __( 'Email' ) . '</label>'.
      ( $req ? '<span class="required">*</span>' : '' ).
      '<input id="email" name="email" type="text" value="'. esc_attr( $commenter['comment_author_email'] ) .
      '" size="30"  tabindex="2"' . $aria_req . ' /></p>';

    $fields[ 'url' ] = '<p class="comment-form-url">'.
      '<label for="url">' . __( 'Website' ) . '</label>'.
      '<input id="url" name="url" type="text" value="'. esc_attr( $commenter['comment_author_url'] ) .
      '" size="30"  tabindex="3" /></p>';

    $fields[ 'phone' ] = '<p class="comment-form-phone">'.
      '<label for="phone">' . __( 'Phone' ) . '</label>'.
      '<input id="phone" name="phone" type="text" size="30"  tabindex="4" /></p>';

  return $fields;
}

In the next step, we have to add a text field for the comment’s title and a radio list for rating the article. These fields cannot be added to the default fields for the author’s information above because even logged-in users will need to input these. This time we have not filtered any default function, but we have added new actions altogether. The comment_form_logged_in_after action adds the input fields below the status message that is displayed to logged-in users, just above the comment input box. It will not be activated for users who are not logged in. To show the input fields to non-logged-in users, we have added the comment_form_after_fields action, which displays the fields below the default fields for the author’s information. We have marked the rating field as required, which we’ll take care of later. Instead of using plain HTML for the radio input boxes, we have used simple code that runs a loop and renders the input boxes with the relevant values until there are five of them.

// Add fields after default fields above the comment box, always visible

add_action( 'comment_form_logged_in_after', 'additional_fields' );
add_action( 'comment_form_after_fields', 'additional_fields' );

function additional_fields () {
  echo '<p class="comment-form-title">'.
  '<label for="title">' . __( 'Comment Title' ) . '</label>'.
  '<input id="title" name="title" type="text" size="30"  tabindex="5" /></p>';

  echo '<p class="comment-form-rating">'.
  '<label for="rating">'. __('Rating') . '<span class="required">*</span></label>
  <span class="commentratingbox">';

    //Current rating scale is 1 to 5. If you want the scale to be 1 to 10, then set the value of $i to 10.
    for( $i=1; $i <= 5; $i++ )
    echo '<span class="commentrating"><input type="radio" name="rating" id="rating" value="'. $i .'"/>'. $i .'</span>';

  echo'</span></p>';

}

Our comment form has the input fields, but they are useless until we have a system for saving the data inputted by users. By adding an action to the comment_post hook, we devise a method for saving the values of meta data if these are not blank. We should make sure not to save blank meta data fields in order to keep the database table from being cluttered with empty rows. We’re also sanitizing the inputted data using the wp_filter_nohtml_kses filter.

Here is the default usage of the add_comment_meta function:

add_comment_meta($comment_id, $meta_key, $meta_value, $unique = false)

In the code, $comment_id is the comment’s default ID set by WordPress. It will be left as is to allow for processing of all comments. The $meta_key stands for the names of the fields as set by us. In this case, the meta keys are the phone number, comment title and rating. Here is how we implement the function in our plugin:

// Save the comment meta data along with comment

add_action( 'comment_post', 'save_comment_meta_data' );
function save_comment_meta_data( $comment_id ) {
  if ( ( isset( $_POST['phone'] ) ) && ( $_POST['phone'] != '') )
  $phone = wp_filter_nohtml_kses($_POST['phone']);
  add_comment_meta( $comment_id, 'phone', $phone );

  if ( ( isset( $_POST['title'] ) ) && ( $_POST['title'] != '') )
  $title = wp_filter_nohtml_kses($_POST['title']);
  add_comment_meta( $comment_id, 'title', $title );

  if ( ( isset( $_POST['rating'] ) ) && ( $_POST['rating'] != '') )
  $rating = wp_filter_nohtml_kses($_POST['rating']);
  add_comment_meta( $comment_id, 'rating', $rating );
}

Remember marking the ratings field as required? Let’s tell WordPress to refuse comments without a rating. We’ll add a function to the preprocess_comment filter that will be applied to the comment data before it is saved. We’re checking whether the ratings field is empty and then displaying an error message if it is.

// Add the filter to check whether the comment meta data has been filled

add_filter( 'preprocess_comment', 'verify_comment_meta_data' );
function verify_comment_meta_data( $commentdata ) {
  if ( ! isset( $_POST['rating'] ) )
  wp_die( __( 'Error: You did not add a rating. Hit the Back button on your Web browser and resubmit your comment with a rating.' ) );
  return $commentdata;
}

Now we have our additional input fields in the comment form. We will use the following function to retrieve the comment’s meta data:

get_comment_meta( $comment_id, $meta_key, $single = false )

If we had been working with a theme, then all of the codes above would have gone into the functions.php file, and the code below would have been included in the comment template. Because we are creating a plugin, we will modify the comment’s output and inject our meta data into it. To do this, we’ll make use of the comment_text filter. In the code below, we first retrieve the URL of the plugin’s folder, which is required only because we will be using images saved in that folder (if we were using the codes in a theme, it would have been the URL of the style sheet’s directory or the theme’s directory).

Depending on whether the comment data is set, we might have to retrieve the comment data and text and then add them to the comment section, with the desired formatting. In the code below, the comment’s title is appended to the beginning of the comment’s text, while the rating images and value are added at the end.

// Add the comment meta (saved earlier) to the comment text
// You can also output the comment meta values directly to the comments template  

add_filter( 'comment_text', 'modify_comment');
function modify_comment( $text ){

  $plugin_url_path = WP_PLUGIN_URL;

  if( $commenttitle = get_comment_meta( get_comment_ID(), 'title', true ) ) {
    $commenttitle = '<strong>' . esc_attr( $commenttitle ) . '</strong><br/>';
    $text = $commenttitle . $text;
  } 

  if( $commentrating = get_comment_meta( get_comment_ID(), 'rating', true ) ) {
    $commentrating = '<p class="comment-rating">  <img src="'. $plugin_url_path .
    '/ExtendComment/images/'. $commentrating . 'star.gif"/><br/>Rating: <strong>'. $commentrating .' / 5</strong></p>';
    $text = $text . $commentrating;
    return $text;
  } else {
    return $text;
  }
}

Now, our plugin is ready for us to add the desired input fields in the comment form and to display the meta data with comments. We could stop here, but we won’t. WordPress allows us to edit comments, and we want the option to edit the information entered in these meta fields as well. Therefore, we will continue coding our plugin and add an option to edit these meta fields from the comment editing screen.

We’ll add a meta box on the comment editing page using the add_meta_boxes_comment hook, which tells WordPress to add the reference meta box to the comment editing page. In the function, we’ll add a meta box using the add_meta_box function, the details of which you can check in the WordPress Codex5.

add_meta_box( $id, $title, $callback, $post_type, $context, $priority, $callback_args );

We’re using the meta boxes to add the form fields, along with a wp_nonce_field for security. In the callback function, we retrieve the meta data before proceeding. We then recreate the same set of input fields as were added in the comment form; the only difference is that here, we also show the value. For the rating radio field, we have again used a simple loop; this time checking whether the radio should be checked comes in handy. Using the resulting input fields, we can now modify the meta data added to comments.

// Add an edit option to comment editing screen  

add_action( 'add_meta_boxes_comment', 'extend_comment_add_meta_box' );
function extend_comment_add_meta_box() {
    add_meta_box( 'title', __( 'Comment Metadata - Extend Comment' ), 'extend_comment_meta_box', 'comment', 'normal', 'high' );
}

function extend_comment_meta_box ( $comment ) {
    $phone = get_comment_meta( $comment->comment_ID, 'phone', true );
    $title = get_comment_meta( $comment->comment_ID, 'title', true );
    $rating = get_comment_meta( $comment->comment_ID, 'rating', true );
    wp_nonce_field( 'extend_comment_update', 'extend_comment_update', false );
    ?>
    <p>
        <label for="phone"><?php _e( 'Phone' ); ?></label>
        <input type="text" name="phone" value="<?php echo esc_attr( $phone ); ?>" class="widefat" />
    </p>
    <p>
        <label for="title"><?php _e( 'Comment Title' ); ?></label>
        <input type="text" name="title" value="<?php echo esc_attr( $title ); ?>" class="widefat" />
    </p>
    <p>
        <label for="rating"><?php _e( 'Rating: ' ); ?></label>
      <span class="commentratingbox">
      <?php for( $i=1; $i <= 5; $i++ ) {
        echo '<span class="commentrating"><input type="radio" name="rating" id="rating" value="'. $i .'"';
        if ( $rating == $i ) echo ' checked="checked"';
        echo ' />'. $i .' </span>';
        }
      ?>
      </span>
    </p>
    <?php
}

As our last step, we need to devise a mechanism for saving the modified data from the editing screen. This is quite similar to the process for saving the meta data from a comment form. Here, we use the edit_comment function to verify the nonce key, and then we update or delete the comment meta field.

// Update comment meta data from comment editing screen 

add_action( 'edit_comment', 'extend_comment_edit_metafields' );

function extend_comment_edit_metafields( $comment_id ) {
    if( ! isset( $_POST['extend_comment_update'] ) || ! wp_verify_nonce( $_POST['extend_comment_update'], 'extend_comment_update' ) ) return;

  if ( ( isset( $_POST['phone'] ) ) && ( $_POST['phone'] != '') ) :
  $phone = wp_filter_nohtml_kses($_POST['phone']);
  update_comment_meta( $comment_id, 'phone', $phone );
  else :
  delete_comment_meta( $comment_id, 'phone');
  endif;

  if ( ( isset( $_POST['title'] ) ) && ( $_POST['title'] != '') ):
  $title = wp_filter_nohtml_kses($_POST['title']);
  update_comment_meta( $comment_id, 'title', $title );
  else :
  delete_comment_meta( $comment_id, 'title');
  endif;

  if ( ( isset( $_POST['rating'] ) ) && ( $_POST['rating'] != '') ):
  $rating = wp_filter_nohtml_kses($_POST['rating']);
  update_comment_meta( $comment_id, 'rating', $rating );
  else :
  delete_comment_meta( $comment_id, 'rating');
  endif;

}

Our plugin is still missing one critical thing: the ability to automatically delete the meta data for comments should we need to remove the plugin. We can easily instruct WordPress to delete all of the custom comment meta data with a small snippet of code. We just need to create a new file, uninstall.php, in the same folder as our plugin’s file and add the code below to it. This code will first check whether the plugin’s uninstall command is set to true. If so, it retrieves all of the comments and runs a foreach loop to delete the three meta fields. The uninstall command is initiated only when you delete the plugin through WordPress’ dashboard.

<?php
if( !defined( 'ABSPATH') && !defined('WP_UNINSTALL_PLUGIN') )
    exit();

  $comments = get_comments();
  foreach($comments as $comment) {
    delete_comment_meta($comment->comment_ID, 'phone');
    delete_comment_meta($comment->comment_ID, 'title');
    delete_comment_meta($comment->comment_ID, 'rating');
  }

Download the Extend Comment WordPress Plugin6

comment-plugin-example7
Screenshot of the Extend Comment plugin installed on the default WordPress theme

Conclusion

You can find a rating system implemented in the comments area of hosting review pages on Web Hosting Rock8. It was added directly to the theme to allow for some flexibility and control over the ratings in user comments. We’ve now learned how to use custom meta fields to modify and extend the comment forms in WordPress posts, pages and custom posts. We’ve made use of conditional tags for greater control and customization. And we can restrict these custom fields to certain post types by forcing the functions that add custom input fields to be executed only if the “post type” conditions are met. Now, your comment forms need not be so boring. Add this extra element of fun and interactivity.

(al)

Footnotes

  1. 1 http://www.smashingmagazine.com/wp-content/uploads/2012/04/comment-wordpress-plugin.jpg
  2. 2 http://www.flickr.com/photos/31878512@N06/4704140020/
  3. 3 http://codex.wordpress.org/Function_Reference/add_comment_meta
  4. 4 http://codex.wordpress.org/Function_Reference/comment_form
  5. 5 http://codex.wordpress.org/Function_Reference/add_meta_box
  6. 6 http://www.smashingmagazine.com/wp-content/uploads/2012/05/ExtendComment.zip
  7. 7 http://www.smashingmagazine.com/wp-content/uploads/2012/05/comment-plugin-example.jpg
  8. 8 http://webhostingrock.com/reviews/

↑ Back to top Tweet itShare on Facebook

Pritam @ Specky Geek loves creating WordPress themes and dabbles in web designing in his spare time after a day job as a wordsmith. He also blogs about genuine methods of making money online. You can follow him on Twitter at @pphans.

Advertisement
  1. 1

    Very nice tutorial, can you please tell how to put a custom div class at end of comment form.

    3
  2. 52

    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’…. 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.

    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?

    I understand that the problem is caused by bad coding practices on the theme, but would like to find a workaround.

    Thanks….Rick…

    2

↑ Back to top