Pregunta PHP: "Aviso: variable indefinida", "Aviso: índice indefinido" y "Aviso: compensación indefinida"


Estoy ejecutando un script PHP y sigo recibiendo errores como:

Aviso: variable no definida: mi_nombre_variable en C: \ wamp \ www \ mypath \ index.php en la línea 10

Aviso: índice no definido: my_index C: \ wamp \ www \ mypath \ index.php en la línea 11

La línea 10 y 11 se ve así:

echo "My variable value is: " . $my_variable_name;
echo "My index value is: " . $my_array["my_index"];

¿Qué significan estos errores?

¿Por qué aparecen de repente? Solía ​​usar este script durante años y nunca tuve ningún problema.

¿Qué debo hacer para solucionarlos?

Esta es una pregunta de referencia general para que las personas se vinculen como duplicados, en lugar de tener que explicar el problema una y otra vez. Siento que esto es necesario porque la mayoría de las respuestas del mundo real sobre este tema son muy específicas.

Meta discusión relacionada:


948


origen


Respuestas:


Aviso: variable indefinida

De la gran sabiduría de la PHP Manual:

Confiar en el valor predeterminado de una variable no inicializada es problemático en el caso de incluir un archivo en otro que usa el mismo nombre de variable. También es un importante riesgo de seguridad con register_globals encendido. E_NOTICE el error de nivel se emite en caso de trabajar con variables no inicializadas, pero no en el caso de agregar elementos a la matriz no inicializada. Está establecido() la construcción del lenguaje se puede usar para detectar si una variable ya se ha inicializado. Además y más ideal es la solución de vacío() ya que no genera un mensaje de advertencia o error si la variable no se inicializa.

De Documentación de PHP:

No se genera ninguna advertencia si la variable no existe. Eso significa       vacío() es esencialmente el equivalente concisa a ! isset ($ var) || $ var      == falso.

Esto significa que podrías usar solo empty() para determinar si la variable está configurada, y además verifica la variable contra lo siguiente, 0,"",null.

Ejemplo:

$o = [];
@$var = ["",0,null,1,2,3,$foo,$o['myIndex']];
array_walk($var, function($v) {
    echo (!isset($v) || $v == false) ? 'true ' : 'false';
    echo ' ' . (empty($v) ? 'true' : 'false');
    echo "\n";
});

Pruebe el fragmento de arriba en el 3v4l.org editor de PHP en línea

Aunque PHP no requiere una declaración de variables, sí lo recomienda para evitar algunas vulnerabilidades de seguridad o errores donde uno olvidará dar un valor a una variable que se utilizará más adelante en el script. Lo que hace PHP en el caso de variables no declaradas es emitir un error de nivel muy bajo, E_NOTICE, uno que ni siquiera se informa por defecto, pero el Manual aconseja permitir durante el desarrollo.

Maneras de lidiar con el problema:

  1. Recomendado: Declare sus variables, por ejemplo, cuando intente agregar una cadena a una variable indefinida. O usar isset() / !empty()  para verificar si están declarados antes de hacer referencia a ellos, como en:

    //Initializing variable
    $value = ""; //Initialization value; Examples
                 //"" When you want to append stuff later
                 //0  When you want to add numbers later
    //isset()
    $value = isset($_POST['value']) ? $_POST['value'] : '';
    //empty()
    $value = !empty($_POST['value']) ? $_POST['value'] : '';
    

    Esto se ha vuelto mucho más limpio a partir de PHP 7.0, ahora puedes usar el nulo coalesce operador:

    // Null coalesce operator - No need to explicitly initialize the variable.
    $value = $_POST['value'] ?? '';
    
  2. Establecer un manejador de error personalizado para E_NOTICE y redirigir los mensajes lejos del resultado estándar (tal vez a un archivo de registro):

    set_error_handler('myHandlerForMinorErrors', E_NOTICE | E_STRICT)
    
  3. Desactivar E_NOTICE de informes. Una forma rápida de excluir solo E_NOTICE es:

    error_reporting( error_reporting() & ~E_NOTICE )
    
  4. Suprime el error con el @ operador.

Nota: Se recomienda encarecidamente implementar solo el punto 1.

Aviso: Índice indefinido / Desviación no definida

Este aviso aparece cuando usted (o PHP) intenta acceder a un índice indefinido de una matriz.

Maneras de lidiar con el problema:

  1. Verifique si el índice existe antes de acceder a él. Para esto puedes usar isset() o array_key_exists():

    //isset()
    $value = isset($array['my_index']) ? $array['my_index'] : '';
    //array_key_exists()
    $value = array_key_exists('my_index', $array) ? $array['my_index'] : '';
    
  2. La construcción del lenguaje list() puede generar esto cuando intenta acceder a un índice de matriz que no existe:

    list($a, $b) = array(0 => 'a');
    //or
    list($one, $two) = explode(',', 'test string');
    

Se utilizan dos variables para acceder a dos elementos de matriz, sin embargo, solo hay un elemento de matriz, índice 0, entonces esto generará

Aviso: compensación indefinida: 1

$_POST / $_GET / $_SESSION variable

Los avisos anteriores aparecen a menudo cuando se trabaja con $_POST, $_GET o $_SESSION. por $_POST y $_GET solo tiene que verificar si el índice existe o no antes de usarlo. por $_SESSION debes asegurarte de que la sesión comenzó con session_start() y que el índice también existe.

También tenga en cuenta que las 3 variables son superglobales y son mayúsculas.

Relacionado:


868



Prueba estos

Q1: este aviso significa que $ varname no es   definido en el alcance actual de la   guión.

P2: El uso de las condiciones isset (), empty () antes de usar cualquier variable sospechosa funciona bien.

// recommended solution for recent PHP versions
$user_name = $_SESSION['user_name'] ?? '';

// pre-7 PHP versions
$user_name = '';
if (!empty($_SESSION['user_name'])) {
     $user_name = $_SESSION['user_name'];
}

O, como una solución rápida y sucia:

// not the best solution, but works
// in your php setting use, it helps hiding site wide notices
error_reporting(E_ALL ^ E_NOTICE);

Nota sobre las sesiones:


109



Una alternativa (a menudo desalentada) es la operador de supresión de errores  @. Es un constructo de lenguaje específico para cerrar avisos y advertencias no deseadas, pero debe usarse con cuidado.

En primer lugar, incurre en una penalización de microperformance sobre el uso isset. Eso no se puede medir en aplicaciones del mundo real, pero se debe considerar en iteraciones pesadas de datos. En segundo lugar, podría obstruir la depuración, pero al mismo tiempo, los errores suprimidos se transmiten a los manejadores de errores personalizados (a diferencia de las expresiones de isset decorated).


46



Significa que está probando, evaluando o imprimiendo una variable a la que todavía no le ha asignado nada. Significa que tienes un error tipográfico o que primero debes verificar que la variable se haya inicializado. Verifique sus rutas lógicas, puede establecerse en una ruta pero no en otra.


35



En general, debido a la "mala programación", y la posibilidad de errores ahora o más tarde.

  1. Si es un error, primero haga una asignación adecuada a la variable: $ varname = 0;
  2. Si realmente solo se define algunas veces, pruébelo: if (isset($varname))antes de usarlo
  3. Si es porque lo deletreaste mal, solo corrige eso
  4. Tal vez incluso el cambio de las advertencias en ti Configuración de PHP

33



No quise deshabilitar el aviso porque es útil, pero quería evitar escribir demasiado.

Mi solución fue esta función:

function ifexists($varname)
{
  return(isset($$varname)?$varname:null);
}

Entonces, si quiero hacer referencia a $ name y echo si existe, simplemente escribo:

<?=ifexists('name')?>

Para elementos de matriz:

function ifexistsidx($var,$index)
{
  return(isset($var[$index])?$var[$index]:null);
}

En la página si quiero referirme a $ _REQUEST ['name']:

<?=ifexistsidx($_REQUEST,'name')?>

30



La mejor forma de obtener entrada cuerda es:

$value = filter_input(INPUT_POST, 'value');

Este one-liner es casi equivalente a:

if (!isset($_POST['value'])) {
    $value = null;
} elseif (is_array($_POST['value'])) {
    $value = false;
} else {
    $value = $_POST['value'];
}

Si quieres absolutamente cuerda valor, al igual que:

$value = (string)filter_input(INPUT_POST, 'value');

24