Why on Earth am I getting “undefined_index” errors?

Right, I’m banging my head against a wall here. I’m sure it’s something incredibly simple but I keep getting undefined index errors on all of these variables.

function meta_genus_species() {
    global $post;

    if (isset($post)) {
        $custom = get_post_custom($post->ID);
    }

    if (isset($custom)) {
        $genus = $custom["genus"][0];
        $species = $custom["species"][0];
        $etymology = $custom["etymology"][0];
        $family = $custom["family"][0];
        $common_names = $custom["common_names"][0];
    }

    ?>
<label>Genus:</label>
<input name="genus" value="<?php if(isset($genus)) { echo $genus; } ?>" />
<label>Species:</label>
<input name="species" value="<?php if(isset($species)) { echo $species; } ?>" />
<p><label>Etymology:</label><br />
<textarea cols="50" rows="5" name="etymology"><?php if(isset($etymology)) { echo $etymology; } ?></textarea></p>
<label>Family:</label>
<input name="family" value="<?php if(isset($family)) { echo $family; } ?>" />
<label>Common Names:</label>
<input name="common_names" value="<?php if(isset($common_names)) { echo $common_names; } ?>" />
    <?php
}

I get this for every variable:

Read More

Notice: Undefined index: genus in […]sf-species-profiles.php on line 207

Any ideas?

Related posts

Leave a Reply

3 comments

  1. It’s a common PHP error, usually when you try to access an array member with a non-existent key;

    $array = array( 'hello' => 'world' );
    echo $array['foobar']; // undefined index
    

    You should check for the key first with isset( $array['foobar'] );

    UPDATE: In this case, I would chuck in a loop that sets-up the variables for you, checking for the index in the process.

    foreach ( array( 'genus', 'species', 'etymology', 'family', 'common_names' ) as $var )
        $$var = isset( $custom[ $var ][0] ) ? $custom[ $var ][0] : '';
    
    echo $genus; // prints value of $custom['genus'][0] if set, otherwise empty
    
  2. You are already calling isset() each time you are printing the data to the screen.

    Why not just skip this part:

    if (isset($custom)) {
        $genus = $custom["genus"][0];
        $species = $custom["species"][0];
        $etymology = $custom["etymology"][0];
        $family = $custom["family"][0];
        $common_names = $custom["common_names"][0];
    }
    

    and do this when you print an input:

    <label>Genus:</label>
    <input name="genus" value="<?php if( isset( $custom["genus"][0] ) ) { print $custom["genus"][0]; } ?>" />
    

    The extra variable assignments are not needed and are causing notices to be generated here.

    BTW …

    You need to escape your output before it is printed in a form:

    <label>Genus:</label>
    <input name="genus" value="<?php if(isset($genus)) { echo esc_attr( $genus ); } ?>" />
    <label>Species:</label>
    <input name="species" value="<?php if(isset($species)) { echo esc_attr( $species ); } ?>" />
    <p><label>Etymology:</label><br />
    <textarea cols="50" rows="5" name="etymology"><?php if(isset($etymology)) { echo esc_textarea( $etymology ); } ?></textarea></p>
    <label>Family:</label>
    <input name="family" value="<?php if(isset($family)) { echo esc_attr( $family ); } ?>" />
    <label>Common Names:</label>
    <input name="common_names" value="<?php if(isset($common_names)) { echo esc_attr( $common_names ); } ?>" />
    
  3. An alternative, which has come out of a Twitter discussion on this post, is to change how you’re getting your data. get_post_custom() returns an array of arrays and is what’s causing you headaches. I would recommend using get_post_custom_values() instead:

    function meta_genus_species() {
        global $post;
    
        $genus = get_post_custom_values( 'genus', $post->ID );
        $species = get_post_custom_values( 'species', $post->ID );
        $etymology = get_post_custom_values( 'etymology', $post->ID );
        $family = get_post_custom_values( 'family', $post->ID );
        $common_names = get_post_custom_values( 'common_names', $post->ID );
    
        ?>
    <label>Genus:</label>
    <input name="genus" value="<?php if(isset($genus[0])) { echo esc_attr( $genus[0] ); } ?>" />
    <label>Species:</label>
    <input name="species" value="<?php if(isset($species[0])) { echo esc_attr( $species ); } ?>" />
    <p><label>Etymology:</label><br />
    <textarea cols="50" rows="5" name="etymology"><?php if(isset($etymology[0])) { echo esc_attr( $etymology ); } ?></textarea></p>
    <label>Family:</label>
    <input name="family" value="<?php if(isset($family[0])) { echo esc_attr( $family ); } ?>" />
    <label>Common Names:</label>
    <input name="common_names" value="<?php if(isset($common_names[0])) { echo esc_attr( $common_names ); } ?>" />
        <?php
    }
    

    A better alternative to custom values would be to use custom meta. You can define these as unique, then when you get the custom meta back out of the DB you’ll have one value rather than an indexed array with only one member. Just something to consider.