¿Comprobar si existe var antes de desarmar en PHP?

88

Con informes de errores, o incluso como mejores prácticas, al desarmar una variable en PHP, ¿debería verificar si existe primero (en este caso no siempre existe) y desarmarla, o simplemente desarmarla?

<?PHP
if (isset($_SESSION['signup_errors'])){
    unset($_SESSION['signup_errors']);
}

// OR

unset($_SESSION['signup_errors']);
?>
JasonDavis
fuente
2
Cf. dk2.php.net/unset#77310
jensgram
1
Es más eficiente de NOTusar isset. Eche un vistazo a mi respuesta. Hice pruebas para encontrar la diferencia de velocidad.
Dan Bray

Respuestas:

167

Simplemente desarmarlo, si no existe, no se hará nada.

João Silva
fuente
3
No sabía si lanzaría una advertencia o aviso
JasonDavis
19
@SilentGhost Estoy de acuerdo, parece una prueba tan simple, pero están pidiendo asesoramiento profesional, y aunque es posible que el registro de errores no tenga ningún error / advertencia / aviso que desarme una var indefinida, podría haber otros problemas que no están registrados. Por ejemplo, simplemente llamar a unset significa que PHP rastrea TODOS los datos var porque no puede encontrar nada, mientras que usar if setpodría tener un mejor esquema de indexación. (Solo un ejemplo, el anterior probablemente sea zapatero y ambos enfoques usan el mismo método de verificación de datos).
James
Es cierto, y también es más eficiente. Eche un vistazo a mi respuesta porque he probado la velocidad de usar issetversículos que no usan isset.
Dan Bray
votar en contra: no se pueden desarmar las claves de matriz que no están definidas.
Behnam
1
@jascha dije, ¡no podemos!
Behnam
48

Del manual de PHP :

Con respecto a cierta confusión anteriormente en estas notas sobre qué causa que unset () active avisos al desarmar variables que no existen ...

Desarmar variables que no existen, como en

<?php
unset($undefinedVariable);
?>

no activa un aviso de "Variable indefinida". Pero

<?php
unset($undefinedArray[$undefinedKey]);
?>

activa dos avisos, porque este código es para desarmar un elemento de una matriz; ni $ undefinedArray ni $ undefinedKey están desarmados, simplemente se utilizan para localizar lo que debería estar desarmado. Después de todo, si existieran, aún esperaría que ambos estuvieran presentes después. ¡NO querrás que desaparezca toda tu matriz solo porque desarmas () uno de sus elementos!

Señor Smith
fuente
41
Esto necesita un poco más de aclaración. Puede desarmar claves de matriz que no estén definidas siempre que exista la matriz.
kingmaple
@kristovaher De hecho, esto no aborda el escenario específico que describe el OP.
Mark Amery
21

Utilizando unset de una variable indefinida no causará ningún error (a menos que la variable sea el índice de una matriz (u objeto) que no existe).

Por lo tanto, lo único que debe considerar es qué es lo más eficiente. Es más eficiente no probar con 'isset', como mostrará mi prueba.

Prueba:

function A()
{
    for ($i = 0; $i < 10000000; $i++)
    {
        $defined = 1;
        unset($defined);
    }
}

function B()
{
    for ($i = 0; $i < 10000000; $i++)
    {
        $defined = 1;
        unset($undefined);
    }
}

function C()
{
    for ($i = 0; $i < 10000000; $i++)
    {
        $defined = 1;
        if (isset($defined))
            unset($defined);
    }
}

function D()
{
    for ($i = 0; $i < 10000000; $i++)
    {
        $defined = 1;
        if (isset($undefined))
            unset($undefined);
    }
}

$time_pre = microtime(true);
A();
$time_post = microtime(true);
$exec_time = $time_post - $time_pre;
echo "Function A time = $exec_time ";

$time_pre = microtime(true);
B();
$time_post = microtime(true);
$exec_time = $time_post - $time_pre;
echo "Function B time = $exec_time ";

$time_pre = microtime(true);
C();
$time_post = microtime(true);
$exec_time = $time_post - $time_pre;
echo "Function C time = $exec_time ";

$time_pre = microtime(true);
D();
$time_post = microtime(true);
$exec_time = $time_post - $time_pre;
echo "Function D time = $exec_time";
exit();

Resultados:

  1. Function A time = 1.0307259559631
    • Definido sin isset
  2. Function B time = 0.72514510154724
    • Indefinido sin isset
  3. Function C time = 1.3804969787598
    • Definido usando isset
  4. Function D time = 0.86475610733032
    • Indefinido usando isset

Conclusión:

Siempre es menos eficiente de usar isset, sin mencionar la pequeña cantidad de tiempo extra que se necesita para escribir. Es más rápido intentar con unsetuna variable indefinida que comprobar si puede serlo unset.

Dan Bray
fuente
1
¡Esto es mucho mejor que la respuesta aceptada! Gracias por realizar estas pruebas.
Adam Friedman
3

Si desea desarmar una variable, puede usar unset

unset($any_variable); // bool, object, int, string etc

Verificar su existencia no tiene ningún beneficio al intentar desarmar una variable.

Si la variable es una matriz y desea desarmar un elemento, debe asegurarse de que el padre exista primero, esto también se aplica a las propiedades del objeto.

unset($undefined_array['undefined_element_key']); // error - Undefined variable: undefined_array

unset($undefined_object->undefined_prop_name); // error - Undefined variable: undefined_object

Esto se resuelve fácilmente envolviendo el unseten un if(isset($var)){ ... }bloque.

if(isset($undefined_array)){
    unset($undefined_array['undefined_element_key']); 
}

if(isset($undefined_object)){
    unset($undefined_object->undefined_prop_name); 
}

La razón por la que solo verificamos la variable ( padre ) es simplemente porque no necesitamos verificar la propiedad / elemento y hacerlo sería mucho más lento de escribir y calcular, ya que agregaría una verificación adicional.

if(isset($array)){
...
}

if(isset($object)){
...
}

.vs

$object->prop_name = null;
$array['element_key'] = null;

// This way elements/properties with the value of `null` can still be unset.

if(isset($array) && array_key_exists('element_key', $array)){
...
}

if(isset($object) && property_exists($object, 'prop_name')){
...
}

// or 

// This way elements/properties with `null` values wont be unset.

if(isset($array) && $array['element_key'])){
...
}

if(isset($object) && $object->prop_name)){
...
}

No hace falta decirlo, pero también es crucial que conozca el valor typede la variable al obtener, configurar y desarmar un elemento o propiedad; el uso de la sintaxis incorrecta arrojará un error.

Es lo mismo cuando se intenta anular el valor de una matriz u objeto multidimensional. Debe asegurarse de que exista el nombre o la clave principal.

if(isset($variable['undefined_key'])){
    unset($variable['undefined_key']['another_undefined_key']);
}

if(isset($variable->undefined_prop)){
    unset($variable->undefined_prop->another_undefined_prop);
}

Cuando se trata de objetos, hay otra cosa en la que pensar y es la visibilidad.

El hecho de que exista no significa que tenga permiso para modificarlo.

TarranJones
fuente
Finalmente, una respuesta adecuada. Gracias.
wp78de
Una pequeña actualización: en PHP 7.4 / 8.0 no se genera ningún error cuando se tiene unsetla propiedad de un objeto principal no existente. Sin embargo, alterar una clave en una matriz no existente en PHP8 genera no solo un aviso sino una advertencia (sujeto a cambios).
wp78de
1

Consulte este enlace https://3v4l.org/hPAto

La herramienta en línea muestra compatibilidad de código para diferentes versiones de PHP

Según esta herramienta el código

unset($_SESSION['signup_errors']);

funcionaría para PHP> = 5.4.0 sin darle ningún aviso / advertencia / error.

evgpisarchik
fuente