name - Arrays PHP y solución a errores de ''índice indefinido''
undefined index php post solucion (10)
Averigüe qué claves están en la matriz $ output, y complete las que faltan con cadenas vacías.
$keys = array_keys($output);
$desired_keys = array(''author'', ''new_icon'', ''admin_link'', ''etc.'');
foreach($desired_keys as $desired_key){
if(in_array($desired_key, $keys)) continue; // already set
$output[$desired_key] = '''';
}
Estoy trabajando con un código hecho por un desarrollador anterior. Soy bastante nuevo en PHP, así que me pregunto si existe algún patrón o solución conocida para este problema.
Básicamente, el autor original no comprueba ningún índice de matriz antes de intentar usarlos. Sé que puedo usar isset () para verificar cada uno antes de usarlo, pero ahora hay cientos de líneas donde aparecen estos errores. Antes de poner música y comenzar a golpear mi cabeza con el teclado, quiero asegurarme de que no haya ningún atajo para manejar esto. Aquí hay una sección típica del código que estoy viendo:
/* snip */
"text" => $link . $top_pick_marker . $output[''author''] . " " . " " .
$output[''new_icon''] . $output[''rec_labels''] . " "
. $output[''admin_link'']
. $output[''alternate_title'']
. $output[''access_info'']
. $output[''description'']
. $output[''url'']
. $output[''subject_terms'']
. $output[''form_subdivisions'']
. $output[''dates_of_coverage'']
. $output[''update_frequency'']
. $output[''place_terms''],
/* snip */
Entonces sé que puedo usar isset () aquí para cada artículo. Tendría que reorganizar un poco las cosas y eliminar toda la concatenación tal como está ahora. ¿Hay alguna otra manera fácil de hacer esto o simplemente estoy atascado con eso?
Esta es la solución más rápida que puedo pensar, pero de lejos no es la mejor. Así que véalo como una "solución de emergencia":
// ...
. @$output[''admin_link'']
. @$output[''alternate_title'']
. @$output[''access_info'']
// ...
El @
suprime todas las advertencias y errores de PHP.
Establecer cada índice en la matriz al principio (o antes de que se use la matriz $output
) probablemente sea la solución más fácil para su caso.
Ejemplo
$output[''admin_link''] = ""
$output[''alternate_title''] = ""
$output[''access_info''] = ""
$output[''description''] = ""
$output[''url''] = ""
También no es realmente relevante para su caso, pero cuando dijo que era nuevo en PHP y esto no es realmente obvio, isset()
puede tomar múltiples argumentos. Así que en lugar de esto:
if(isset($var1) && isset($var2) && isset($var3) ...){
// all are set
}
Tu puedes hacer:
if(isset($var1, $var2, $var3)){
// all are set
}
La misma idea que Michael Waterfall
De CodeIgniter
// Lets you determine whether an array index is set and whether it has a value.
// If the element is empty it returns FALSE (or whatever you specify as the default value.)
function element($item, $array, $default = FALSE)
{
if ( ! isset($array[$item]) OR $array[$item] == "")
{
return $default;
}
return $array[$item];
}
Podría intentar usar una pequeña función que devolverá el valor si existe o una cadena vacía si no. Esto es lo que uso:
function arrayValueForKey($arrayName, $key) {
if (isset($GLOBALS[$arrayName]) && isset($GLOBALS[$arrayName][$key])) {
return $GLOBALS[$variable][$key];
} else {
return '''';
}
}
Entonces puedes usarlo así:
echo '' Values: '' . arrayValueForKey(''output'', ''admin_link'')
. arrayValueForKey(''output'', ''update_frequency'');
¡Y no arrojará ningún error!
¡Espero que esto ayude!
Puede usar isset () sin perder la concatenación:
//snip
$str = ''something''
. ( isset($output[''alternate_title'']) ? $output[''alternate_title''] : '''' )
. ( isset($output[''access_info'']) ? $output[''access_info''] : '''' )
. //etc.
También podría escribir una función para devolver la cadena si está configurada, esto probablemente no sea muy eficiente:
function getIfSet(& $var) {
if (isset($var)) {
return $var;
}
return null;
}
$str = getIfSet($output[''alternate_title'']) . getIfSet($output[''access_info'']) //etc
No recibirá un aviso porque la variable se pasa por referencia.
Si mantiene el código anterior, probablemente no pueda aspirar a "el mejor código posible" ... Ese es un caso en el que, en mi opinión, podría reducir el nivel de error_reporting
.
Este " índice indefinido " solo debe ser Avisos; por lo tanto, puede establecer el nivel error_reporting
para excluir avisos.
Una solución es con la función error_reporting
, como esta:
// Report all errors except E_NOTICE
error_reporting(E_ALL ^ E_NOTICE);
Lo bueno de esta solución es que puede configurarla para excluir avisos solo cuando sea necesario (digamos, por ejemplo, si solo hay uno o dos archivos con ese tipo de código)
Otra solución sería establecer esto en php.ini (podría no ser una buena idea si está trabajando en varias aplicaciones, ya que podría enmascarar avisos útiles); ver error_reporting
en php.ini.
Pero insisto: esto es aceptable solo porque está manteniendo una aplicación anterior; ¡no debería hacer eso cuando desarrolle un nuevo código!
Una solución corta es esto (PHP 5.3+):
$output[''alternate_title''] = $output[''alternate_title''] ?:'''';
Obtiene el valor de la variable, si no se evalúa como falso, o la expresión falsa. (El que está después de '':'')
El uso del operador ternario, sin el parámetro "si es verdadero", devolverá el resultado de la expresión de prueba (el primero). Como no definido se evalúa como falso, se devolverá la expresión falsa.
En PHP 7 existe el operador de fusión nulo ligeramente más elegante:
$output[''alternate_title''] = $output[''alternate_title''] ?? '''';
(Sería bueno con un operador de asignación predeterminado como ''? ='')
Una variación de la respuesta de SquareRootOf2, pero debe colocarse antes del primer uso de la variable $ output:
$keys = array(''key1'', ''key2'', ''etc'');
$output = array_fill_keys($keys, '''');
foreach($i=0; $i<10; $i++){
$v = @(array)$v;
// this could help defining $v as an array.
//@ is to supress undefined variable $v
array_push($v, $i);
}