0

I'm using this code here for repeating fields in a CPT (yes, I know of ACF and a few others), and have tried to add a third field.

The field is currently displaying in the meta box, and is output on the front end. However, inside the meta box field - when it is empty - is a

"Notice of Undefined Index: role... on line 235" (I'll denote which line that is below),

and on the front end is says

"Notice: Undefined index: role... on line 29"

on my single-discog-item.php file.

I can update and save the field in the backend and display it on the front end, but I can't make these Notices go away, even after a bit of sniffing around the web.

Any suggestions on how to solve this

    add_action('admin_init', 'add_meta_boxes', 1);
function add_meta_boxes() {
    add_meta_box( 'repeatable-fields',
        'Personnel Listing:',
        'awc_discog_meta_two',
        'discog-item',
        'normal',
        'high');
}

function awc_discog_meta_two() {
    global $post;

    $repeatable_names = get_post_meta($post->ID, 'repeatable_names', true);

    wp_nonce_field( 'repeatable_meta_box_nonce', 'repeatable_meta_box_nonce' );
?>
    <script type="text/javascript">
        //THE JS WORKS FINE
    </script>

    <table id="repeatable-fieldset-one" width="100%">
    <thead>
        <tr>
            <th width="2%"></th>
            <th width="30%">Name</th>
            <th width="20%">Role</th>
            <th width="40%">URL</th>
            <th width="2%"></th>
        </tr>
    </thead>
    <tbody>
    <?php

    if ( $repeatable_names ) :

        foreach ( $repeatable_names as $field ) {
?>
    <tr>
        <td><a class="button remove-row" href="#" title="Remove This Item">-</a></td>
        <td><input type="text" class="widefat" name="name[]" value="<?php if($field['name'] != '') echo esc_attr( $field['name'] ); ?>" placeholder="Charles Mingus"/></td>
//THE NEXT LINE IS LINE 235
        <td><input type="text" class="widefat" name="role[]" value="<?php if($field['role'] != '') echo esc_attr( $field['role'] ); ?>" placeholder="guitar/oud"/></td>
        <td><input type="text" class="widefat" name="url[]" value="<?php if ($field['url'] != '') echo esc_attr( $field['url'] ); ?>" placeholder="http://"/></td>
        <td><a class="sort">Sort</a></td>

    </tr>
    <?php
        }
    else :
        // show a blank one
?>
    <tr>
        <td><a class="button remove-row" href="#" title="Remove This Item">-</a></td>
        <td><input type="text" class="widefat" name="name[]" placeholder="Charles Mingus"/></td>
        <td><input type="text" class="widefat" name="role[]" placeholder="guitar/oud" /></td>
        <td><input type="text" class="widefat" name="url[]" placeholder="http://" /></td>
<td><a class="sort">Sort</a></td>

    </tr>
    <?php endif; ?>

    <!-- empty hidden one for jQuery -->
    <tr class="empty-row screen-reader-text">
        <td><a class="button remove-row" href="#">-</a></td>
        <td><input type="text" class="widefat" name="name[]" placeholder="Charles Mingus"/></td>
        <td><input type="text" class="widefat" name="role[]" placeholder="guitar/oud" /></td>
        <td><input type="text" class="widefat" name="url[]" placeholder="http://" /></td>
<td><a class="sort">Sort</a></td>

    </tr>
    </tbody>
    </table>

    <p><a id="add-row" class="button" href="#">Add another</a>
    <input type="submit" class="metabox_submit" value="Save" />
    </p>

    <?php
}

add_action('save_post', 'repeatable_meta_box_save');
function repeatable_meta_box_save($post_id) {
    if ( ! isset( $_POST['repeatable_meta_box_nonce'] ) ||
        ! wp_verify_nonce( $_POST['repeatable_meta_box_nonce'], 'repeatable_meta_box_nonce' ) )
        return;

    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
        return;

    if (!current_user_can('edit_post', $post_id))
        return;

    $old = get_post_meta($post_id, 'repeatable_names', true);
    $new = array();


    $names = $_POST['name'];
    $roles = $_POST['role'];
    $urls = $_POST['url'];


    $count = count( $names );

    for ( $i = 0; $i < $count; $i++ ) {

        if ( $roles[$i] != '' ) 
            $new[$i]['role'] = stripslashes( strip_tags( $roles[$i] ) );


        if ( $names[$i] != '' ) :
            $new[$i]['name'] = stripslashes( strip_tags( $names[$i] ) );



        if ( $urls[$i] == 'http://' )
            $new[$i]['url'] = '';
        else
            $new[$i]['url'] = stripslashes( $urls[$i] ); // and however you want to sanitize
        endif;
    }

    if ( !empty( $new ) && $new != $old )
        update_post_meta( $post_id, 'repeatable_names', $new );
    elseif ( empty($new) && $old )
        delete_post_meta( $post_id, 'repeatable_names', $old );
}

this is from the single-discog-item.php

<?php
$args = array( 'post_type' => 'discog-item', 'posts_per_page' => -1 );
$loop = new WP_Query( $args );
$repeatable_names = get_post_meta($post->ID, 'repeatable_names', true);
while ( $loop->have_posts() ) : $loop->the_post();
  the_title();
  echo '<div class="entry-content">

  if (!empty($repeatable_names)) {

      echo '<ul class="personnel">';
      foreach ($repeatable_names as $field) { 

        $the_name = $field['name'];
//THE NEXT LINE IS LINE 29
        $the_role = $field['role'];
        $the_url = $field['url'];

        echo '<li>';

        if (!empty($the_name)) {
            echo $the_name;
        }

        if (!empty($the_role)) {
            echo $the_role;
        }

        if (!empty($the_url)) {
            echo '<a href="' . $the_url . '" target="_blank">Visit Website</a>';
        }

        echo '</li>';
  }

  echo '</ul>';
} else {
    echo "Nothing to see here...";
}

  the_content();
  echo '</div>';
endwhile;
?>
4
  • $field['role'] has not yet been set which means you are trying to use something that does not exist. You have to check if you correctly registered this new field, also, first check if the field exists before using it. Oct 16, 2014 at 6:26
  • thanks @PieterGoosen, I don't how to do that, and can't see where in the above it occurs for the other two fields $field['name'] and $field['url']. I'm fairly new to PHP, and this repeatable field stuff has thrown me for a loop (no pun intended).
    – alexwc_
    Oct 16, 2014 at 13:52
  • I have tested your code and it works fine. I can also not see anything out of place, except that you have a syntax error in your single page and this line $repeatable_names = get_post_meta($post->ID, 'repeatable_names', true); should be inside your loop, not outside. Apart from that, I'm not getting any notices Oct 16, 2014 at 14:38
  • It only displays the error when the role field is empty, other than that it seems to work fine....
    – alexwc_
    Oct 16, 2014 at 15:13

1 Answer 1

1

From your comments, this only happens when the fields are left empty. This means that the particular field does not get set.

As stated in my comments, you should first check if a field is set before you try to use it. In the first block of code, you have the following three lines

<td><input type="text" class="widefat" name="name[]" value="<?php if($field['name'] != '') echo esc_attr( $field['name'] ); ?>" placeholder="Charles Mingus"/></td>
<td><input type="text" class="widefat" name="role[]" value="<?php if($field['role'] != '') echo esc_attr( $field['role'] ); ?>" placeholder="guitar/oud"/></td>
<td><input type="text" class="widefat" name="url[]" value="<?php if ($field['url'] != '') echo esc_attr( $field['url'] ); ?>" placeholder="http://"/></td>

For fail save, you should check all three fields if they are set by using isset before displaying them. To fix your error backend, change these three lines to

<td><input type="text" class="widefat" name="name[]" value="<?php if( isset( $field['name'] ) ) echo esc_attr( $field['name'] ); ?>" placeholder="Charles Mingus"/></td>
<td><input type="text" class="widefat" name="role[]" value="<?php if( isset( $field['role'] ) ) echo esc_attr( $field['role'] ); ?>" placeholder="guitar/oud"/></td>
<td><input type="text" class="widefat" name="url[]" value="<?php if( isset( $field['url'] ) ) echo esc_attr( $field['url'] ); ?>" placeholder="http://"/></td>

You need to do the exact same thing in your single page (second block of code). As pointed out in comments, you have a syntax error, I don't know if this is just a copy and paste error, but

echo '<div class="entry-content">

should be

echo '<div class="entry-content">';

Also

$repeatable_names = get_post_meta($post->ID, 'repeatable_names', true);

should be in your loop, not outside

This is how your code should look like in your single page template

<?php
$args = array( 
    'post_type' => 'discog-item', 
    'posts_per_page' => -1 
);
$loop = new WP_Query( $args );

while ( $loop->have_posts() ) {
    $loop->the_post();
    the_title();

    echo '<div class="entry-content">';
        $repeatable_names = get_post_meta($post->ID, 'repeatable_names', true);

        if (!empty($repeatable_names)) {

            echo '<ul class="personnel">';
                foreach ($repeatable_names as $field) { 

                    echo '<li>';

                        if(isset($field['name'])){
                            echo $field['name'];
                        }   
                        if(isset($field['role'])){
                            echo $field['role'];
                        }
                        if(isset($field['url'])){
                            echo '<a href="' . $field['url'] . '" target="_blank">Visit Website</a>';
                        }

                    echo '</li>';
                }

        echo '</ul>';

        } else {

            echo "Nothing to see here...";

        }

        the_content();
    echo '</div>';
}
?>      
1
  • My pleasure, glad it worked. Enjoy :-) Oct 16, 2014 at 16:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.