¿Por qué estoy recibiendo errores "undefined_index"?

23 jun 2011, 13:14:20
Vistas: 19.2K
Votos: 4

Estoy desesperado con esto. Seguro que es algo super sencillo pero sigo recibiendo errores de índice indefinido en todas estas variables.

function meta_genus_species() {
    global $post;

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

    if (isset($custom)) {
        $genus = $custom["genus"][0];    // Error aquí si 'genus' no existe
        $species = $custom["species"][0]; // Error aquí si 'species' no existe
        $etymology = $custom["etymology"][0]; // Error aquí si 'etymology' no existe
        $family = $custom["family"][0];  // Error aquí si 'family' no existe
        $common_names = $custom["common_names"][0]; // Error aquí si 'common_names' no existe
    }

    ?>
<label>Género:</label>
<input name="genus" value="<?php if(isset($genus)) { echo $genus; } ?>" />
<label>Especie:</label>
<input name="species" value="<?php if(isset($species)) { echo $species; } ?>" />
<p><label>Etimología:</label><br />
<textarea cols="50" rows="5" name="etymology"><?php if(isset($etymology)) { echo $etymology; } ?></textarea></p>
<label>Familia:</label>
<input name="family" value="<?php if(isset($family)) { echo $family; } ?>" />
<label>Nombres comunes:</label>
<input name="common_names" value="<?php if(isset($common_names)) { echo $common_names; } ?>" />
    <?php
}

Recibo este error para cada variable:

Notice: Undefined index: genus en [...]sf-species-profiles.php en la línea 207

¿Alguna idea?

2
Comentarios

¿qué línea de código es la línea 207?

Scott Scott
23 jun 2011 13:24:10

$genus = $custom["genus"][0];

turbonerd turbonerd
23 jun 2011 14:25:26
Todas las respuestas a la pregunta 3
2

Es un error común en PHP, que suele ocurrir cuando intentas acceder a un elemento de un array con una clave que no existe:

$array = array( 'hello' => 'world' );
echo $array['foobar']; // índice indefinido

Deberías verificar primero la clave con isset( $array['foobar'] );

ACTUALIZACIÓN: En este caso, yo incluiría un bucle que configure las variables por ti, verificando el índice en el proceso.

foreach ( array( 'genus', 'species', 'etymology', 'family', 'common_names' ) as $var )
    $$var = isset( $custom[ $var ][0] ) ? $custom[ $var ][0] : '';

echo $genus; // imprime el valor de $custom['genus'][0] si está definido, de lo contrario vacío
23 jun 2011 13:23:26
Comentarios

¿Estás sugiriendo que use isset en cada línea, como (pseudocódigo) isset($custom[genus]) > $genus=$custom[genus]? Seguramente esa es una forma terriblemente larga de hacer las cosas. Tenía la impresión (y esta es la primera vez que me encuentro con este problema) que usar isset en $post y luego también en $custom significaría que esas variables no están definidas/no existen a menos que haya datos en $post?

turbonerd turbonerd
23 jun 2011 14:25:12

Para nada - pero de cualquier manera, nunca deberías asumir que X existe. Mira mi respuesta actualizada :)

TheDeadMedic TheDeadMedic
23 jun 2011 14:52:54
5

Ya estás llamando a isset() cada vez que imprimes los datos en pantalla.

¿Por qué no simplemente omitir esta parte:

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];
}

y hacer esto cuando imprimes un input:

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

Las asignaciones de variables adicionales no son necesarias y están generando avisos aquí.

Por cierto...

Necesitas escapar tu salida antes de que se imprima en un formulario:

<label>Género:</label>
<input name="genus" value="<?php if(isset($genus)) { echo esc_attr( $genus ); } ?>" />
<label>Especie:</label>
<input name="species" value="<?php if(isset($species)) { echo esc_attr( $species ); } ?>" />
<p><label>Etimología:</label><br />
<textarea cols="50" rows="5" name="etymology"><?php if(isset($etymology)) { echo esc_textarea( $etymology ); } ?></textarea></p>
<label>Familia:</label>
<input name="family" value="<?php if(isset($family)) { echo esc_attr( $family ); } ?>" />
<label>Nombres comunes:</label>
<input name="common_names" value="<?php if(isset($common_names)) { echo esc_attr( $common_names ); } ?>" />
23 jun 2011 15:58:16
Comentarios

Sí, no me molesto en escapar hasta que tengo el código funcionando.. :) Consideré hacerlo como sugieres, pero soy un poco maniático de la estética del código y ¡Dios mío que se ve feo! Gracias.

turbonerd turbonerd
23 jun 2011 16:32:00

Supongo que somos diferentes entonces... No me molesto en imprimir en pantalla a menos que los datos estén escapados y nunca introduzco complejidad innecesaria para que el código se vea "bonito".

mfields mfields
23 jun 2011 16:39:22

¡Jaja! En mi humilde opinión, creo que los sitios hackeados con enlaces farmacéuticos en el pie de página son más feos que ese código. ;)

John P Bloch John P Bloch
23 jun 2011 16:45:33

No te obsesiones con que $custom["genus"][0] sea "más feo" que $genus. El código de @mfields es exactamente igual al tuyo por lo demás, pero no devolverá un error. Escribe tanto código como necesites para realizar un trabajo, ni más, ni menos.

EAMann EAMann
23 jun 2011 17:12:50

Je, como señala EAMann, no es el escape lo que veo como feo - era a $custom["genus"][0] en lugar de $genus a lo que me refería. Ciertamente no estoy sugiriendo que no escaparía datos porque los hiciera feos.. :)

turbonerd turbonerd
23 jun 2011 17:41:38
1

Una alternativa, que surgió de una discusión en Twitter sobre esta publicación, es cambiar cómo obtienes tus datos. get_post_custom() devuelve un array de arrays y es lo que está causando tus dolores de cabeza. Recomendaría usar get_post_custom_values() en su lugar:

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>Género:</label>
<input name="genus" value="<?php if(isset($genus[0])) { echo esc_attr( $genus[0] ); } ?>" />
<label>Especie:</label>
<input name="species" value="<?php if(isset($species[0])) { echo esc_attr( $species ); } ?>" />
<p><label>Etimología:</label><br />
<textarea cols="50" rows="5" name="etymology"><?php if(isset($etymology[0])) { echo esc_attr( $etymology ); } ?></textarea></p>
<label>Familia:</label>
<input name="family" value="<?php if(isset($family[0])) { echo esc_attr( $family ); } ?>" />
<label>Nombres comunes:</label>
<input name="common_names" value="<?php if(isset($common_names[0])) { echo esc_attr( $common_names ); } ?>" />
    <?php
}

Una mejor alternativa a los valores personalizados sería usar meta personalizados. Puedes definirlos como únicos, así cuando recuperes los meta personalizados de la base de datos tendrás un solo valor en lugar de un array indexado con un solo miembro. Solo algo para considerar.

23 jun 2011 17:10:00
Comentarios

Gracias EAMann. Investigaré los valores personalizados/metadatos cuando llegue a casa y luego contemplaré ese enfoque.

turbonerd turbonerd
23 jun 2011 17:43:02