Verifique se var existe antes de cancelar a configuração no PHP?

89

Com o relatório de erros ativado, ou mesmo como prática recomendada, ao remover a configuração de uma variável no PHP, você deve verificar se ela existe primeiro (neste caso, nem sempre existe) e removê-la ou apenas removê-la?

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

// OR

unset($_SESSION['signup_errors']);
?>
JasonDavis
fonte
2
Cf. dk2.php.net/unset#77310
jensgram
1
É mais eficiente de NOTusar isset. Dê uma olhada na minha resposta. Fiz testes para descobrir a diferença de velocidade.
Dan Bray

Respostas:

171

Apenas desabilite, se não existir nada será feito.

João silva
fonte
3
Eu não sabia se iria lançar um aviso ou aviso
JasonDavis
20
@SilentGhost Eu concordo, parece um teste tão simples, mas eles estão pedindo conselhos profissionais e, embora o log de erros possa não ter nenhum erro / aviso / aviso cancelando uma var indefinida, pode haver outros problemas que não foram registrados. por exemplo, apenas chamar unset significa que o PHP vasculha TODOS os dados var porque não consegue encontrar nada, enquanto o uso if setpode ter um esquema de indexação melhor. (Apenas um exemplo, o anterior provavelmente é de sapateiros e ambas as abordagens usam o mesmo método de verificação de dados).
James,
É verdade, e é mais eficiente também. Dê uma olhada na minha resposta porque testei a velocidade de uso de issetversículos que não usam isset.
Dan Bray
vote down - você não pode remover as chaves do array que não estão definidas.
Behnam
1
@jascha eu disse, não podemos!
Behnam
48

Do Manual do PHP :

Em relação a alguma confusão no início destas notas sobre o que faz com que unset () acione avisos ao cancelar a configuração de variáveis ​​que não existem ....

Desconfigurando variáveis ​​que não existem, como em

<?php
unset($undefinedVariable);
?>

não dispara um aviso de "Variável indefinida". Mas

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

dispara dois avisos, porque este código é para cancelar a configuração de um elemento de uma matriz; nem $ undefinedArray nem $ undefinedKey estão sendo desabilitados, eles estão apenas sendo usados ​​para localizar o que deveria ser desabilitado. Afinal, se eles existissem, você ainda esperaria que os dois existissem depois. Você NÃO gostaria que seu array inteiro desaparecesse apenas porque você desarmou () um de seus elementos!

Senhor Smith
fonte
42
Isso precisa de um pouco mais de esclarecimento. Você pode remover as chaves de array que não estão definidas, desde que o próprio array exista.
kingmaple
@kristovaher Na verdade - isso não aborda o cenário específico que o OP descreve.
Mark Amery,
23

Usar unsetem uma variável indefinida não causará nenhum erro (a menos que a variável seja o índice de um array (ou objeto) que não existe).

Portanto, a única coisa que você precisa considerar é o que é mais eficiente. É mais eficiente não testar com 'isset', como meu teste irá mostrar.

Teste:

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 sem isset
  2. Function B time = 0.72514510154724
    • Indefinido sem isset
  3. Function C time = 1.3804969787598
    • Definido usando isset
  4. Function D time = 0.86475610733032
    • Indefinido usando isset

Conclusão:

É sempre menos eficiente de usar isset, sem falar na pequena quantidade de tempo extra que leva para escrever. É mais rápido tentar unsetuma variável indefinida do que verificar se ela pode ser unset.

Dan Bray
fonte
1
Isso é muito melhor do que a resposta aceita! Obrigado por executar esses testes.
Adam Friedman
3

Se você gostaria de remover uma variável, então você pode apenas usar unset

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

Verificar sua existência não traz nenhum benefício ao tentar remover a definição de uma variável.

Se a variável é um array e você deseja remover a definição de um elemento, você deve se certificar de que o pai existe primeiro, isso também se aplica às propriedades do objeto.

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

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

Isso é facilmente resolvido envolvendo o unsetem um if(isset($var)){ ... }bloco.

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

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

A razão pela qual apenas verificamos a variável ( pai ) é simplesmente porque não precisamos verificar a propriedade / elemento e fazer isso seria muito mais lento para escrever e calcular, pois adicionaria uma verificação extra.

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)){
...
}

Isso nem é preciso dizer, mas também é crucial que você conheça a função typeda variável ao obter, definir e remover a definição de um elemento ou propriedade; usar a sintaxe errada gerará um erro.

É o mesmo ao tentar remover o valor de uma matriz ou objeto multidimensional. Você deve certificar-se de que a chave / nome pai existe.

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

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

Ao lidar com objetos, há outra coisa em que pensar, que é a visibilidade.

Só porque existe, não significa que você tem permissão para modificá-lo.

TarranJones
fonte
Finalmente, uma resposta adequada. Obrigado.
wp78de
Uma pequena atualização: No PHP 7.4 / 8.0 nenhum erro é lançado quando você unsetaltera a propriedade de um objeto pai não existente. No entanto, alterar uma chave em um array não existente no PHP8 levanta não apenas um aviso, mas um aviso (sujeito a alterações).
wp78de
1

Verifique este link https://3v4l.org/hPAto

A ferramenta online mostra compatibilidade de código para diferentes versões de PHP

De acordo com esta ferramenta, o código

unset($_SESSION['signup_errors']);

funcionaria para PHP> = 5.4.0 sem dar a você nenhum aviso / aviso / erro.

evgpisarchik
fonte