4

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:

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

Any ideas?

2
  • which line of code is line 207?
    – Scott
    Jun 23, 2011 at 10:24
  • $genus = $custom["genus"][0];
    – turbonerd
    Jun 23, 2011 at 11:25

3 Answers 3

5

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
  • Are you suggesting I use isset on every line, such as (pseudo) isset($custom[genus]) > $genus=$custom[genus]? Surely that's a hellishly long-winded way of doing things. I was under the impression (and this is the first time I've encountered this problem) that using isset on $post then also $custom would mean that those variables aren't set/don't exist unless there is data in $post?
    – turbonerd
    Jun 23, 2011 at 11:25
  • 1
    Not at all - but either way, you should never assume X exists. See my updated answer :) Jun 23, 2011 at 11:52
4

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 ); } ?>" />
5
  • Yeah, I don't bother escaping until I've got working code.. :) I did contemplate doing it the way you've suggested, but I'm a bit of a code-aesthetics freak and dear Lord that looks ugly! Thank you.
    – turbonerd
    Jun 23, 2011 at 13:32
  • 1
    I guess we are different then ... I don't bother printing to the screen unless I the data is escaped and I never introduce unnecessary complexity make code look "pretty".
    – mfields
    Jun 23, 2011 at 13:39
  • 1
    LOL! IMHO I think hacked sites with pharmaceutical links in the footer are uglier than that code. ;) Jun 23, 2011 at 13:45
  • Don't get hung up on $custom["genus"][0] being "uglier" than $genus. @mfields' code is otherwise exactly the same as yours, but it won't return an error. Write as much code as you need to in order to get a job done, no more, no less.
    – EAMann
    Jun 23, 2011 at 14:12
  • Heh, as EAMann points out, it isn't the escaping that I see as ugly - it's $custom["genus"][0] rather than $genus that I was referring to. I'm most certainly not suggesting that I wouldn't escape data because it made it ugly.. :)
    – turbonerd
    Jun 23, 2011 at 14:41
2

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.

1
  • Thanks EAMann. I'll research custom values/meta when I get home then contemplate that approach.
    – turbonerd
    Jun 23, 2011 at 14:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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