Support » Developing with WordPress » adding and editing non-required field in comments

  • Resolved ejm

    (@llizard)


    In spite of only really knowing enough about php coding to get myself in trouble, I find I cannot stop trying anyway….

    So far, I have managed to introduce an extra field (not required) to my comment form. I have also managed to get the field to appear in the admin area. If the extra field is filled in from the front end, it appears in the editing comment area of admin. However, if the field has not been filled in OR if it is emptied in the editing section of admin, the field remains empty and cannot be edited. (I did try to achieve this using a plugin and ran into exactly the same problem.)

    Staring at various parts of the Codex as well as googling, I am wondering if I need to introduce

    update_post_meta($meta_value); AND/OR update_user_meta( $prev_value )

    For either of these, I am entirely unclear on how to add them to my child theme’s functions file.

    Where have I gone wrong in the following, and/or can someone point to where to find the answer? This is the coding I have put into my child theme’s functions file so far:

        /*...............
        add a field to the comment form
        ...............*/
        function add_comment_fields($newfield) {
            $newfield['webname'] = '<p class="comment-form-author" title="this field is optional"><label for="webname">' . __( 'Website Name' ) . '</label>' .
                '<input id="webname" name="webname" type="text" size="30" /></p>';
            return $newfield;
        }
        add_filter('comment_form_default_fields','add_comment_fields');
    
        // add it to the admin area
        function add_comment_meta_values($comment_id) {
           if ( ( isset( $_POST['webname'] ) ) && ( $_POST['webname'] != '') ) {
                $webname = wp_filter_nohtml_kses($_POST['webname']);
                add_comment_meta($comment_id, 'webname', $webname);
            } 
        }
        add_action ('comment_post', 'add_comment_meta_values', 1);
    
        // attach it to author
        function comment_edit_function( $comment_id )
        {
            if( isset( $_POST['webname'] ) )
              update_comment_meta( $comment_id, 'webname', esc_attr( $_POST['webname'] ) );
        }
        add_filter( 'get_comment_author_link', 'attach_websitename_to_author' );
    
        function attach_websitename_to_author( $author ) {
            $webname = get_comment_meta( get_comment_ID(), 'webname', true );
            if ( $webname )
                $author .= " ($webname)";
            return $author;
        }
    
        // Register meta box on comment edit screen
        function webname_comment_edit_add_meta_box() {
            add_meta_box( 'title', __( 'website name', 'text-domain' ), 'webname_comment_meta_box', 'comment', 'normal', 'high' );
        }
        add_action( 'add_meta_boxes_comment', 'webname_comment_edit_add_meta_box' );
    
        // Callback function for displaying the comment meta box.
        function webname_comment_meta_box( $comment ) {
            $webname = get_comment_meta( $comment->comment_ID, 'webname', true );
            wp_nonce_field( 'webname_comment_fields_update', 'webname_comment_fields_update', false );
            ?>
            <p>
                <label for="webname"><?php _e( 'Website Name', 'text-domain' ); ?></label>
                <input type="text" name="webname" value="<?php echo esc_attr( $webname ); ?>" class="widefat" />
            </p><?php
        }
    
        // Update comment meta data from comment editing screen 
        add_action( 'edit_comment', 'webname_comment_edit_meta_fields' );
        function webname_comment_edit_meta_fields( $comment_id ) {
            if ( ! isset( $_POST['webname_comment_fields_update'] ) || 
                     ! wp_verify_nonce( $_POST['webname_comment_fields_update'], 'webname_comment_fields_update' )
            ) {
                return;
            }
    
          if ( ( isset( $_POST['webname'] ) ) && ( $_POST['webname'] != '' ) ) {
                $webname = wp_filter_nohtml_kses( $_POST['webname'] );
                update_comment_meta( $comment_id, 'webname', $webname );
          } else {
                delete_comment_meta( $comment_id, 'webname');
          }
        }
    
        $webname = get_comment_meta( $comment->comment_ID, 'webname', true );
        echo esc_html( $webname );
    
        /*.......
        for the admin area
         from https://wpengineer.com/2214/adding-input-fields-to-the-comment-form/
         ....*/ 
        function save_comment_meta_data( $comment_id ) {
            add_comment_meta( $comment_id, 'webname', $_POST[ 'webname' ] );
        }
        add_action( 'comment_post', 'save_comment_meta_data' );

    Please note that this is an update on the question I posed in “fixing wordpress” that, on reflection (there have been zero responses), possibly does not belong there.

    Thank you for any help you can offer.

Viewing 15 replies - 1 through 15 (of 25 total)
  • Moderator bcworkz

    (@bcworkz)

    Use the update_*() form of the functions in place of where you use the add_*() form. The update variant will add if the record does not already exist. The add variant will not update an existing record.

    When a field is empty, no data is sent, not even an empty string. Yet, if a comment exists, you should have a record of your field for that comment, even if it is an empty string. When you check if your field is present with isset(), no record is created for the comment when isset() returns false. Change the logic to always save something as long as the comment is created, regardless of the field’s isset() result. You use isset() to decide if you save an empty string or the passed value, not to decide if anything should be saved at all.

    Thread Starter ejm

    (@llizard)

    Thank you for your reply, bcworkz.

    That makes sense that if the field is empty, no data is sent. And intellectually, I understand what you mean by “Change the logic to always save something as long as the comment is created, regardless of the field’s isset() result. You use isset() to decide if you save an empty string or the passed value, not to decide if anything should be saved at all.

    Alas, I do not know how to implement this.

    I thought it might be with the function update_option() but as usual, the codex is written for people who probably already know the answer to the question.

    Not to mention that apparently, update_option() “has been deprecated […] in favor of update() method instead” (https://developer.wordpress.org/reference/classes/wp_customize_setting/_update_option/).

    Is https://developer.wordpress.org/reference/classes/wpdb/update/ the page that might contain the information I need?

    Because I couldn’t wrap my head around the wp developer update page I took a shot and tried removing the “if isset” with the following:

    function update_comment_meta_values($comment_id) {
    if ( $_POST['webname'] != '') {
            $webname = wp_filter_nohtml_kses($_POST['webname']);
            add_comment_meta($comment_id, 'webname', $webname);
        } 
    }
    add_action ('comment_post', 'update_comment_meta_values', 1);

    It will probably come as no surprise to you that this did not work.

    Staring more at the coding at the bottom of the page on wpdb::update, I’m guessing that this contains clues to what I am trying to achieve. Is there another place I can refer to (something a little more along the lines of “wp for dummies”) to glean the answer?

    
    public function update( $table, $data, $where, $format = null, $where_format = null ) {
        if ( ! is_array( $data ) || ! is_array( $where ) ) {
            return false;
        }
     
        $data = $this->process_fields( $table, $data, $format );
        if ( false === $data ) {
            return false;
        }
        $where = $this->process_fields( $table, $where, $where_format );
        if ( false === $where ) {
            return false;
        }
     
        $fields = $conditions = $values = [... etc. etc. ...]
    Moderator bcworkz

    (@bcworkz)

    No, the wpdb::update() is the wrong substitute. The replacement for WP_Customize_Setting::_update() is WP_Customize_Setting::update().
    https://developer.wordpress.org/reference/classes/wp_customize_setting/update/

    What does this have to do with saving comment meta? It’s for saving theme options in the customizer. I suggest you use update_comment_meta() in place of add_comment_meta(). You also asked about update_post_meta() and update_user_meta(). Those are good replacements for using the add_*() variants, but again, I don’t see what that has to do with comments. But then I don’t fully understand what you’re trying to accomplish. From what you’ve been asking, it wasn’t that important until references to functions unrelated to comments started happening 🙂

    As for the logic I suggested earlier, you have this now (pseudo code):

    function() {
      if $_POST value is set, then save the value
    }

    You can assume if the action fires, a comment is being saved. Your function should be more like this:

    function() {
      if $_POST value is set,
        then save the value
      else
        save an empty string
    }
    Thread Starter ejm

    (@llizard)

    Thank you for your reply and your patience with a rank beginner.

    re:

    I don’t fully understand what you’re trying to accomplish.

    I have added an optional field “website name” to my comments form. If it is filled in, I would like it to appear in the comments area on my WP as “commenter’s name (commenter’s website name)” AND in the editing area for the comments. If it is NOT filled in, I do not want empty parentheses to appear in the comments area on my WP.

    At this point, if the field is filled in, it appears on my WP as expected, as well as appearing in the editing area for the comments in WP-admin. However, if I try to edit the empty field in WP-admin, it remains empty. If I remove an entered value on the new optional field, it stays empty and cannot be filled in again. (I hope this is making sense.)

    I will work on implementing the following so that there is an empty string.

    function() {
      if $_POST value is set,
        then save the value
      else
        save an empty string
    }

    I’m guessing I’ll also somehow have to add an elseif to the following that if the string is empty, the parentheses should NOT appear.

    function webname_comment_meta_box( $comment ) {
        $webname = get_comment_meta( $comment->comment_ID, 'webname', true );
        wp_nonce_field( 'webname_comment_fields_update', 'webname_comment_fields_update', false );
        ?>
        <p>
            <label for="webname"><?php _e( 'Website Name', 'text-domain' ); ?></label>
            <input type="text" name="webname" value="<?php echo esc_attr( $webname ); ?>" class="widefat" />
        </p><?php
    }

    Something like if $webname == '' {echo ''} ???

    Moderator bcworkz

    (@bcworkz)

    OK, so customizer, post meta, and user meta functions would not come into play AFAIK. I’m following your explanation except for how the parentheses appear when the field is not filled in.

    In any case, you don’t need conditional logic on output, only upon form submit. For output, just echo out whatever is in comment meta, whether it be the saved value or an empty string. You’ll have an issue still for existing comments without an associated stored value.

    Thread Starter ejm

    (@llizard)

    Than you again, for your response.

    re:

    I’m following your explanation except for how the parentheses appear when the field is not filled in.

    At this point, the parentheses do not appear if the field is not filled in. But if I put in an instruction to save an empty string if the value is ”, then wouldn’t it appear in the comment meta box as ()?

    function attach_websitename_to_author( $author ) {
        $webname = get_comment_meta( get_comment_ID(), 'webname', true );
        if ( $webname )
            $author .= " ($webname)";
       return $author;
     }
    

    Not knowing how to do it (and having tried a number of incorrect bits of code) I’m guessing that I have to say something like

    if ($_POST['webname'] = '')
       echo ' ';

    This didn’t throw any errors. But it also doesn’t seem to do anything….

    re:

    [Y]ou don’t need conditional logic on output, only upon form submit. For output, just echo out whatever is in comment meta, whether it be the saved value or an empty string.

    Once again, I understand the logic here, but am not certain of which code sections are used for the form submit. Is it this part??

    function add_comment_meta_values($comment_id) {
       if ( ( isset( $_POST['webname'] ) ) && ( $_POST['webname'] != '') ) {
            $webname = wp_filter_nohtml_kses($_POST['webname']);
            add_comment_meta($comment_id, 'webname', $webname);
        } 
    }
    add_action ('comment_post', 'add_comment_meta_values', 1);
    Moderator bcworkz

    (@bcworkz)

    Well, a single space is still a stored value, though it might get stripped by WP code because output is sometimes passed through trim(). I just noticed you have $author .= " ($webname)";. That is where the parentheses are coming from. You’re using if ( $webname ) to conditionally check for an assigned value, which is good, but now that we’re storing empty strings at times, it’s going to add ” ()” for empty strings (or a trimmed space). Change your conditional to if ( isset( $webname ) && '' != $webname ).

    Yes, the “comment_post” action fires when the comment form has been submitted and the comment added to the DB.

    Thread Starter ejm

    (@llizard)

    I fear that I may have to start all over. No matter what changes I make, everything appears to be working exactly as before: the field remains filled in if it is filled in at the outset and cannot be removed or changed; the field remains empty if it is not filled in at the outset and cannot be filled in from the admin area….

    I just noticed you have $author .= " ($webname)";. That is where the parentheses are coming from. You’re using if ( $webname ) to conditionally check for an assigned value, which is good, but now that we’re storing empty strings at times, it’s going to add ” ()” for empty strings (or a trimmed space).

    This is what I thought was going to happen if I asked it to store an empty string. But, judging from the fact that an empty field does not appear as ” ()” beside the author, I guess I have not succeeded in storing the empty string.

    I’ll keep chipping away over the next few days. Maybe, by a miracle, it will suddenly work. I’ll report back.

    Many thanks for your help. I now have a vague inkling about which functions do what.

    Moderator bcworkz

    (@bcworkz)

    You’re welcome. Even if you need to start over, it’s clear to me that you’ve learned some important lessons, so it’s not a complete loss. So far, I’ve just been making quick observations from the sidelines, partly because I’ve been rather busy this past week. Thankfully, the crunch is almost over. If you like, I’d be willing to try out your code on my own test site to see if I can shed any more light into what the problem might be. You probably should post the current version of your complete custom field code for me to work with since the version in your OP isn’t entirely applicable any more.

    Better yet, post the code over at pastebin.com. If you sign up there (for free, but not required), you’d be able to go back and edit your code later on in case you want to show me an updated version. Then you can simply provide the link to your code here. When you submit your code over there, it’s helpful if you specify PHP syntax highlighting be used in its display.

    Thread Starter ejm

    (@llizard)

    Thank you!

    Post the code over at pastebin.com. If you sign up there (for free, but not required), you’d be able to go back and edit your code later on in case you want to show me an updated version.

    I have done as you suggested. I suspect that there may be duplicate pieces of code….

    Here is what I have in my child functions file: pastebin[dot]com/FJtVCvt2

    No matter what I do, I cannot seem to get the field to be editable and if the field is left empty, it simply does not appear at all.

    I tried it in a test WP as well, with the same results….

    Moderator bcworkz

    (@bcworkz)

    Long post here, get comfortable 🙂

    The reason you cannot properly edit the field is your webname_comment_edit_meta_fields() function code is messed up. (surprise!! 🙂 ) Additionally, below that function you have

    $webname = get_comment_meta( $comment->comment_ID, 'webname', true );
    echo esc_html( $webname );

    outside of any function declarations. It appears to be stray code left over from some earlier editing. It doesn’t belong there and isn’t needed, so remove it. FYI, code in functions.php should never echo out anything when the page is loaded. echo statements can only occur within function declarations on this page.

    If you have not defined WP_DEBUG as true in wp-config.php, you should do so while working on custom code like this. The warnings it outputs can be hard to see in the admin area, but you might see a brief flash of output just before the page loads. In any case, it’ll still be visible at the top of the page when using the page source view of your browser. If WP_DEBUG is true and your code isn’t working as expected, it’s worth checking source view for any messages.

    The above misplaced code would generate warnings like “array index comment_ID does not exist” or “variable comment undefined”, along with line number and file reference. Any kind of debug output is not good (but informative) and should be resolved. Be sure WP_DEBUG is returned to false when you’re done coding on publicly accessible sites because leaving it as true introduces a slight security risk.

    One more general comment before talking about specific problems with the function. If you are not using a text editor that somehow indicates matching (or the lack of matching) parentheses, braces, brackets, etc., consider using one that does. Most programmer oriented editors will do this. This is a hint to one of the problems with your function code, there are misplaced curly braces. Best resolved with the right kind of editor.

    The first if() conditional resolves as true when the nonce check fails, so the function should return without doing anything. So far so good. But look what other code is contained in the same conditional block (delimited by curly braces). The first update_comment_meta() function! But can never execute because return is encountered first.

    Incidentally, the default comment form handler does its own nonce check, so you don’t really need to do your own nonce check. It doesn’t hurt to do so anyway. Better safe than sorry!

    You do have a second update_comment_meta() call that’s outside the nonce check conditional block, but look where the add_action() for ‘edit_comment’ call occurs. It’s within the function declaration that it’s supposed to call, so the action is never added to start with. Thus the function is never called.

    In short, you need to resolve the curly brace placement and remove the redundant update code. Part of the problem with curly braces I think is that you’ve confused the two different styles of conditional statements. PHP lesson time!

    The usual style is a conditional block of code delimited by curly braces:

    if ( isset( $variable )) {
       conditional_function_call( $variable );
       another_conditional_call();
    }
    non_conditional_call();

    There’s a shortcut style for one line of conditional code without braces:

    if ( isset( $variable ))
       conditional_function_call( $variable );
    non_conditional_call();

    Only conditional_function_call() depends on $variable being set, non_conditional_call() will always execute. It’s easy to confuse what’s what when using the shortcut style, so many PHP style guides recommend that the shortcut style never be used, always use curly braces, even for one line conditionals.

    One last thing. The conditional statement
    if ( isset( $_POST['webname'] ) && '' != $webname )
    is incorrect. $webname in this context is undefined. You should have done
    if ( isset( $_POST['webname'] ) && '' != $_POST['webname'])

    But on further thought since I suggested that logic, in a form handling context, that’s not quite right either. It’s redundant logic. If $_POST[‘webname’] is set, it’ll never be an empty string. That’s how forms work, empty field values are never passed. So why check for an empty string? No harm in doing so, but there’s no point to it.

    Because we want to store an empty string when $_POST[‘webname’] is not set, you should do something more like this:

    if ( isset( $_POST['webname'])) {
       $value = esc_attr( $_POST['webname']);
    } else {
       $value = '';
    }
    update_comment_meta( $comment_id, 'webname', $value );

    There may be some fine tuning left to do, but if you properly correct the “edit_comment” action stuff, you’ll be able to edit the field from the admin area.

    Thread Starter ejm

    (@llizard)

    Thank you, bcworkz! I have been away from the computer pretty much all day and have just seen your reply. It is a lot to digest…. Here’s hoping I can apply what you have kindly set out. I’ll report back in the next couple of days. Many thanks again for your patience and care!

    Moderator bcworkz

    (@bcworkz)

    I’m happy to help anyone who appreciates it. Take your time, better to fully grasp what’s going on than to knock something out.

    Thread Starter ejm

    (@llizard)

    That took a lot less time than expected! Good idea to add define( 'WP_DEBUG', true ); in my test WP’s config file. That was most helpful. The first thing that came up was a very easy fix on another part of the comment customizaton, once I realized the variable had to be defined inside the curly bracket of the function…

    Notice: Undefined variable: commenter in ../wp-content/themes/my-child-theme/functions.php on line 140

    function modify_comment_form_fields($fields){
    	$commenter = 0;
        $fields['url'] = '<p class="comment-form-url"><label for="url">' . __( 'Path on Web', 'domainreference' ) . '</label>' .
        '<input id="url" name="url" type="text" value="' . esc_attr( $commenter['comment_author_url'] ) .

    I was also missing opening curly bracket after if ( isset ( $_POST[‘webname’] )

    /*..........
    Update comment meta data from comment editing screen 
     ....*/ 
    function webname_comment_edit_meta_fields( $comment_id ) {
        if ( isset( $_POST['webname'] ) && '' != $_POST['webname']) {
            update_comment_meta( $comment_id, 'webname', esc_attr( $_POST['webname'] ) );
        }
    
    }

    But the main problem and the reason for the inability to edit was because I had the add-action placed erroneously inside final curly bracket of the webname_comment_edit_meta_fields( $comment_id ) function!

    add_action( 'edit_comment', 'webname_comment_edit_meta_fields' );

    Once again, many many thanks for your patient and very helpful answers, bcworkz. It’s thrilling to be able to mark this as resolved.

    Here is the full coding I ended up with (that probably still needs cleaning up, but at least it’s working!):

    /*...............
    add a field to the comment form
    ...............*/
    function add_comment_fields($newfield) {
        $newfield['webname'] = '<p class="comment-form-author" title="this field is optional"><label for="webname">' . __( 'Your Site\'s Name' ) . '</label>' .
            '<input id="webname" name="webname" type="text" size="30" /></p>';
        return $newfield;
    }
    add_filter('comment_form_default_fields','add_comment_fields');
    
    function add_comment_meta_values($comment_id) {
       if ( ( isset( $_POST['webname'] ) ) && ( $_POST['webname'] != '') ) {
    	$webname = wp_filter_nohtml_kses($_POST['webname']);
            add_comment_meta($comment_id, 'webname', $webname);
        } 
    	else    
    		$webname = '&nbsp;';
    }
    add_action ('comment_post', 'add_comment_meta_values', 1);
    
    function comment_edit_function( $comment_id )
    {
        if( isset( $_POST['webname'] ) )
          update_comment_meta( $comment_id, 'webname', esc_attr( $_POST['webname'] ) );
        else 
    		$_POST['webname'] = '&nbsp;';
    }
    
    add_filter( 'get_comment_author_link', 'attach_websitename_to_author' );
    
    function attach_websitename_to_author( $author ) {
        $webname = get_comment_meta( get_comment_ID(), 'webname', true );
        if ( $webname )
            $author .= " ($webname)";
    	elseif ($webname = '')
    		$author .= " $webname";
       return $author;
     }
    
    // Register meta box on comment edit screen
    function webname_comment_edit_add_meta_box() {
        add_meta_box( 'title', __( 'website name', 'text-domain' ), 'webname_comment_meta_box', 'comment', 'normal', 'high' );
    }
    add_action( 'add_meta_boxes_comment', 'webname_comment_edit_add_meta_box' );
    
    // Callback function for displaying the comment meta box.
    function webname_comment_meta_box( $comment ) {
        $webname = get_comment_meta( $comment->comment_ID, 'webname', true );
        wp_nonce_field( 'webname_comment_fields_update', 'webname_comment_fields_update', false );
        ?>
        <p>
            <label for="webname"><?php _e( 'Commenter\'s Site Name', 'text-domain' ); ?></label>
            <input type="text" name="webname" value="<?php echo esc_attr( $webname ); ?>" class="widefat" />
        </p><?php
    }
    
    /*..........
    Update comment meta data from comment editing screen 
     ....*/ 
    function webname_comment_edit_meta_fields( $comment_id ) {
        if ( isset( $_POST['webname'] ) && '' != $_POST['webname']) {
            update_comment_meta( $comment_id, 'webname', esc_attr( $_POST['webname'] ) );
        }
    
    }
    add_action( 'edit_comment', 'webname_comment_edit_meta_fields' );
    
    /*.......
     from wpengineer.com/2214/adding-input-fields-to-the-comment-form/
     ....*/ 
    function save_comment_meta_data( $comment_id ) {
        add_comment_meta( $comment_id, 'webname', $_POST[ 'webname' ] );
    }
    add_action( 'comment_post', 'save_comment_meta_data' );
    
    // many thanks to bcworkz for help in fixing adding custom field to comments wordpress.org/support/topic/adding-and-editing-non-required-field-in-comments/
    Thread Starter ejm

    (@llizard)

    Take your time, better to fully grasp what’s going on than to knock something out.

    Once again, you are wise.

    Now that I’ve got it working but am pretty certain the first set of coding falls under the category of not quite fully grasping what is going on, I’ve revised it in my WP test site:

    As you suspected would happen somewhere higher in the thread, now the website variable is showing the parentheses, even when the variable is not filled in.

    I’ve tried various riffs on the following, all producing the parentheses. What am I missing? Because there must be a way to instruct the page to show the parentheses only if that variable is filled in. Shouldn’t there?

    
    // try to show parentheses around webname ONLY if it is filled in
     
    function comment_edit_function( $comment_id )
    {
        if( isset( $_POST['webname'] ) )
          update_comment_meta( $comment_id, 'webname', esc_attr( $_POST['webname'] ) );
        else
        $_POST['webname'] = '&nbsp;';
    }
    add_filter( 'get_comment_author_link', 'attach_websitename_to_author' );
     
    function attach_websitename_to_author( $author ) {
        $webname = get_comment_meta( get_comment_ID(), 'webname', true );
        if ( $webname )
            $author .= " ($webname)";
        elseif ($_POST['webname'] = '&nbsp;')
            $author .= " $webname";
       return $author;
     }

    Here is the full coding:
    pastebin [dot] com/QHNXTwKX

Viewing 15 replies - 1 through 15 (of 25 total)
  • The topic ‘adding and editing non-required field in comments’ is closed to new replies.