I would like to be able to simply add a field to a comment. I know that I can use hook_form_alter() to do it, but what do I need to do to store it in the database and then display it?

I can't find any good references on storing and retrieving/displaying the data submitted by the field. Additionally, if anyone knows of a module that makes a simple implementation of this then that might be a big help.

Comments

nicholas.alipaz’s picture

OK, after quite some time, I have finally done this!

Here is how.

Create a new module with the 3 necessary files: yourmodule.info, yourmodule.install & yourmodule.module

Then inside your .info file you will have something like:

; $Id$
name = Your Module
description = Allows you to add a field to the comment form through the drupal form api
core = 6.x
dependencies[] = comment

Your .install file:

/* this module sets up any tables we need for the data we will be storing
   it may be necessary to alter some of the queries to your needs. */
function yourmodule_schema() {
  $schema['yourmodule'] = array(
    'description' => t('...??'),
    'fields' => array(
      'id' => array(
        'type' => 'serial'
        // zerofill auto_increment
      ),
      'xid' => array(
        'type' => 'int',
        'unsigned' => TRUE
        // default NULL
        // zerofill
      ),
      'type' => array(
        'type' => 'varchar',
        'length' => 16
        // enum('node', 'comment')
        // not null
        // null check
      ),
      'val' => array(
        'type' => 'varchar',
        'length' => 999
        // default NULL
      ),
    ),
    'primary key' => array('id')
  );
  return $schema;
}

function yourmodule_install() {
  drupal_install_schema('yourmodule', 'yourmodule');
}

function yourmodule_uninstall() {
  drupal_uninstall_schema('yourmodule', 'yourmodule');
}

Then in your .module file:


/* Add our new field to the content types and/or comments */
function yourmodule_form_alter(&$form, $form_state, $form_id) { // form override
  if ($form_id == 'forum_node_form') { // add field to forum content type
    unset($form['taxonomy']['5']['#options'][4]);
    $form['cb2vsn'] = array(
    '#type' => 'hidden', // I have used hidden fields here, because this is what I needed, you may also need to change this to suit your needs
    '#id' => t('edit-field-cb2vsn-0-value'),
    '#default_value' => '',
    );
  }
  if ($form_id == 'comment_form') { // add field to comment content type
    $form['cb2vsn'] = array(
    '#type' => 'hidden', // I have used hidden fields here, because this is what I needed, you may also need to change this to suit your needs
    '#id' => t('edit-field-cb2vsn-0-value'),
    '#default_value' => '',
    );
  }
}

/* set up permissions */
function yourmodule_perm() {
  return array('view your field');
}

/* operations for handling the values inserted into a node's form */
function yourmodule_nodeapi(&$node, $op) {
  switch ($op) {
    case 'insert': // insert in the database
      $cb2sig = $node->cb2vsn; // here is my field as created in the last form_alter()
      db_query("INSERT INTO {yourmodule} (xid, type, val) VALUES(%d, '%s', '%s')", $node->nid, 'node', $cb2sig);
      break;
    case 'view': // get it from the database for display
      if (user_access('view your field')) {
        $result = db_fetch_object(db_query("SELECT val FROM {yourmodule} WHERE type='node' AND xid = %d", $node->nid));
        if ($result->val) {
          $node->yourfield = $result->val;
        }
      }
      break;
  }
}

/* operations for handling the values inserted into a comment's form */
function yourmodule_comment(&$comment, $op) {
  switch ($op) {
    case 'insert': // insert in the database
      $cb2sig = $comment['cb2vsn']; // here is my field as created in the last form_alter()
      db_query("INSERT INTO {yourmodule} (xid, type, val) VALUES(%d, '%s', '%s')", $comment['cid'], 'comment', $cb2sig);
      break;
    case 'view': // get it from the database for display
      if (user_access('view your field')) {
        $result = db_fetch_object(db_query("SELECT val FROM {yourmodule} WHERE type='comment' AND xid = %d", $comment->cid));
        $comment->yourfield = $result->val;
      }
      break;
  }
}

The last thing you have to do is to add to your template files: $node->yourfield or $comment->yourfield to display the field where you may need it in the comments or node.

I hope someone gets some use out of this, because I had to search really hard on it. I ended up pulling most of my code out of the user agent module.

oallen’s picture

Ok i'm implementing a similar system on my site with this. Basically I added a new hidden field to my comment form. The field is appearing correctly on the form. But the data is not being entered into the database when I submit the form.

function owen_comment(&$comment, $op) {
  switch($op) {
    case 'insert':
      $pic = $comment['pic'];
      db_query("INSERT INTO owen (cid, nid, pic) VALUES(%d, %d, %d)", $comment['cid'], $comment['nid'], $comment['pic']);
      break;
  }
}

I haven't even started with creating the view for it. Right now when I submit the comment, there is no row added into the database. Any ideas what could be going wrong?

oallen’s picture

Ok I got a little bit farther. The problem was I was not referring to the module as {module} in the database qry. When I fixed that, it worked correctly.

Now the next dilemma is that it is still not correctly adding the value of the hidden field into the database.

So right now i'm grabbing the variable $comment['pic'] but it has no value and is returning 0. I added a print_r($comment) to my module to try and see what variables are available, and sure enough there is no $comment[pic]...

Yet, when I look at the form code prior to submitting there is
<input type="hidden" name="pic" id="edit-pic" value="2" />

So this confuses the heck outta me. I mean the input is there, with a value... yet when I submit, the value isn't in the $comment array.

Argh another 3 hours later and i've gotten nowhere. This is getting rediculously frustrating, for such a simple task. I could have programmed this in PHP by hand in 10 minutes, but to keep in the drupal system I wanted to do it through that. I'm really beginning to doubt the viability of Drupal as the documentation on the internet is absolutely atrocious. This is literally the ONLY page I can find which has ANYTHING about interacting with the database regarding how to add a custom field to the comment form... very very frustrating.

nicholas.alipaz’s picture

could you show us your code, I will try to help if I can. I had to figure this out on my own too.

keanu’s picture

Hi Nicolas,

Could you please take a look at http://drupal.org/node/1350356#comment-5285820 Maybe you can help me with adding additional hostname field to comment form?

apsivam’s picture

instead of custom module, you can also use Node comments module

nicholas.alipaz’s picture

I can't use node comments if I still want to use the forums and advanced forums modules.

I tried Node comments with Node forum in the past and had a few issues. Additionally there are a lot of features that are left to be desired, mark all read, legend, and others. Thanks for the info however.

lovedrupal6’s picture

Hi All,
Very thankful for Nicholas for the detailed account.
This is exactly what I am looking for and I need to add a extra field "Occupation" in the comment form and make it required.

Will be very grateful if any of you can advice me further.
I have followed your advice and code and created a commentfield module with 3 files:

commentfield.install is as below:

<?php
/* this module sets up any tables we need for the data we will be storing it may be necessary to alter some of the queries to your needs. */
function commentfield_schema() {
  $schema['commentfield'] = array(
    'description' => t('...??'),
    'fields' => array(
      'id' => array(
        'type' => 'serial'
        // zerofill auto_increment
      ),
      'xid' => array(
        'type' => 'int',
        'unsigned' => TRUE
        // default NULL
        // zerofill
      ),
      'type' => array(
        'type' => 'varchar',
        'length' => 16
        // enum('node', 'comment')
        // not null
        // null check
      ),
      'val' => array(
        'type' => 'varchar',
        'length' => 999
        // default NULL
      ),
    ),
    'primary key' => array('id')
  );
  return $schema;
}

function commentfield_install() {
  drupal_install_schema('commentfield', 'commentfield');
}

function commentfield_uninstall() {
  drupal_uninstall_schema('commentfield', 'commentfield');
}
?>

commentfield.module is as below:

<?php
/* Add our new field to the content types and/or comments */
function commentfield_form_alter(&$form, $form_state, $form_id) { // form override
  if ($form_id == 'forum_node_form') { // add field to forum content type
    unset($form['taxonomy']['5']['#options'][4]);
    $form['cb2vsn'] = array(
    '#type' => 'hidden', // I have used hidden fields here, because this is what I needed, you may also need to change this to suit your needs
    '#id' => t('edit-field-cb2vsn-0-value'),
    '#default_value' => '',
    );
  }
  if ($form_id == 'comment_form') { // add field to comment content type
    $form['cb2vsn'] = array(
    '#type' => 'hidden', // I have used hidden fields here, because this is what I needed, you may also need to change this to suit your needs
    '#id' => t('edit-field-cb2vsn-0-value'),
    '#default_value' => '',
    );
  }
}

/* set up permissions */
function commentfield_perm() {
  return array('view your field');
}

/* operations for handling the values inserted into a node's form */
function commentfield_nodeapi(&$node, $op) {
  switch ($op) {
    case 'insert': // insert in the database
      $cb2sig = $node->cb2vsn; // here is my field as created in the last form_alter()
      db_query("INSERT INTO {commentfield} (xid, type, val) VALUES(%d, '%s', '%s')", $node->nid, 'node', $cb2sig);
      break;
    case 'view': // get it from the database for display
      if (user_access('view your field')) {
        $result = db_fetch_object(db_query("SELECT val FROM {commentfield} WHERE type='node' AND xid = %d", $node->nid));
        if ($result->val) {
          $node->yourfield = $result->val;
        }
      }
      break;
  }
}

/* operations for handling the values inserted into a comment's form */
function commentfield_comment(&$comment, $op) {
  switch ($op) {
    case 'insert': // insert in the database
      $cb2sig = $comment['cb2vsn']; // here is my field as created in the last form_alter()
      db_query("INSERT INTO {commentfield} (xid, type, val) VALUES(%d, '%s', '%s')", $comment['cid'], 'comment', $cb2sig);
      break;
    case 'view': // get it from the database for display
      if (user_access('view your field')) {
        $result = db_fetch_object(db_query("SELECT val FROM {commentfield} WHERE type='comment' AND xid = %d", $comment->cid));
        $comment->yourfield = $result->val;
      }
      break;
  }
}
?>

Can you please guide me what to edit further so that the field "Occupation" is visible in the comment form along with the text area.

Mant thanks and in anticipation of further guidance,
..Lovedrupal6

pixture’s picture

Sorry for not answering your question. I was looking for a similar solution and came across this post.

I think you may need to add code to support 'update' and 'delete' actions for both hook_nodeapi() and hook_comment().
Otherwise, you will have a old data or orphan over the long term. (although the size of the data would be relatively small).

FYI,

nicholas.alipaz’s picture

I didn't add the update action since I didn't want people to be able to update. I am tracking useragent in comments for my site.

As for delete, yes you may be right on that.

Of course what I posted was more just something that worked for me. Others may need to fix/adjust in some situations.

For the place where it says "forum_node_form" I think that should read "comment_form" to add the field to that particular form, I am not sure why I posted this with that form id. I can't seem to edit it.