is_null - php if post isset




Melhor maneira de testar a existência de uma variável no PHP; isset() está claramente quebrado (12)

Explicando NULL, logicamente pensando

Eu acho que a resposta óbvia para tudo isso é ... Não inicialize suas variáveis ​​como NULL, incialize-as como algo relevante para o que elas pretendem se tornar.

Tratar NULL adequadamente

NULL deve ser tratado como "valor inexistente", que é o significado de NULL. A variável não pode ser classificada como existente para o PHP porque não foi informado que tipo de entidade está tentando ser. Pode também não existir, então o PHP apenas diz: "Tudo bem, isso não acontece porque não tem sentido nisso de qualquer maneira e NULL é a minha maneira de dizer isso".

Um argumento

Vamos discutir agora. "Mas NULL é como dizer 0 ou FALSE ou ''.

Errado, 0-FALSE- '' são todos ainda classificados como valores vazios, mas são especificados como algum tipo de valor ou resposta predeterminada a uma questão. FALSE é a resposta para sim ou não, '' é a resposta ao título que alguém enviou, e 0 é a resposta a quantidade ou tempo, etc. Eles são definidos como algum tipo de resposta / resultado que os torna válidos como sendo definidos.

NULL não é uma resposta, mas isso não nos diz sim ou não e não nos diz o tempo e não nos diz uma string em branco que foi enviada. Essa é a lógica básica na compreensão do NULL.

Resumo

Não se trata de criar funções malucas para contornar o problema, está apenas mudando a maneira como seu cérebro olha para NULL. Se for NULL, assuma que não está definido como nada. Se você estiver pré-definindo variáveis, defina-as como 0, FALSE ou "", dependendo do tipo de uso que você pretende para elas.

Sinta-se à vontade para citar isso. Está fora do topo da minha cabeça lógica :)

Dos documentos do isset() :

isset() will return FALSE if testing a variable that has been set to NULL.

Basicamente, isset() não verifica se a variável está configurada, mas se está configurada para qualquer coisa, exceto NULL .

Dado isso, qual é a melhor maneira de verificar a existência de uma variável? Eu tentei algo como:

if(isset($v) || @is_null($v))

(o @ é necessário para evitar o aviso quando $v não está definido), mas is_null() tem um problema semelhante ao isset() : retorna TRUE em variáveis ​​não definidas! Parece também que:

@($v === NULL)

funciona exatamente como @is_null($v) , então também está fora.

Como devemos verificar confiavelmente a existência de uma variável no PHP?

Edit: há claramente uma diferença no PHP entre as variáveis ​​que não estão definidas e as variáveis ​​que são definidas como NULL :

<?php
$a = array('b' => NULL);
var_dump($a);

O PHP mostra que $a['b'] existe e tem um valor NULL . Se você adicionar:

var_dump(isset($a['b']));
var_dump(isset($a['c']));

você pode ver a ambigüidade da qual estou falando com a função isset() . Aqui está a saída de todos os três destes var_dump()s :

array(1) {
  ["b"]=>
  NULL
}
bool(false)
bool(false)

Além disso edite: duas coisas.

Um, um caso de uso. Uma matriz sendo transformada nos dados de uma UPDATE SQL UPDATE , em que as chaves da matriz são as colunas da tabela e os valores da matriz são os valores a serem aplicados a cada coluna. Qualquer uma das colunas da tabela pode conter um valor NULL , representado pela passagem de um valor NULL na matriz. Você precisa de uma maneira de diferenciar entre uma chave de matriz não existente e um valor de matriz sendo definido como NULL ; essa é a diferença entre não atualizar o valor da coluna e atualizar o valor da coluna para NULL .

Segundo, a resposta do Zoredache , array_key_exists() funciona corretamente, para o meu caso de uso acima e para qualquer variável global:

<?php
$a = NULL;
var_dump(array_key_exists('a', $GLOBALS));
var_dump(array_key_exists('b', $GLOBALS));

saídas:

bool(true)
bool(false)

Uma vez que isso lida corretamente em todos os lugares eu posso ver que existe alguma ambigüidade entre variáveis ​​que não existem e variáveis ​​que são definidas como NULL , estou chamando array_key_exists() a maneira mais fácil oficialmente em PHP para realmente verificar a existência de um variável .

(Apenas outro caso em que posso pensar é para propriedades de classe, para as quais há property_exists() , que, de acordo com seus documentos , funciona de maneira semelhante a array_key_exists() porque distingue corretamente entre não estar definido e estar configurado como NULL .)


Às vezes fico um pouco perdido tentando descobrir qual operação de comparação usar em uma determinada situação. isset() só se aplica a valores não inicializados ou explicitamente nulos. Passar / atribuir nulo é uma ótima maneira de garantir que uma comparação lógica funcione conforme o esperado.

Ainda assim, é um pouco difícil pensar, então aqui está uma matriz simples comparando como diferentes valores serão avaliados por diferentes operações:

|           | ===null | is_null | isset | empty | if/else | ternary | count>0 |
| -----     | -----   | -----   | ----- | ----- | -----   | -----   | -----   |
| $a;       | true    | true    |       | true  |         |         |         |
| null      | true    | true    |       | true  |         |         |         |
| []        |         |         | true  | true  |         |         |         |
| 0         |         |         | true  | true  |         |         | true    |
| ""        |         |         | true  | true  |         |         | true    |
| 1         |         |         | true  |       | true    | true    | true    |
| -1        |         |         | true  |       | true    | true    | true    |
| " "       |         |         | true  |       | true    | true    | true    |
| "str"     |         |         | true  |       | true    | true    | true    |
| [0,1]     |         |         | true  |       | true    | true    | true    |
| new Class |         |         | true  |       | true    | true    | true    |

Para ajustar a tabela, eu comprimi um pouco as etiquetas:

  • $a; refere-se a uma variável declarada mas não atribuída
  • tudo o mais na primeira coluna se refere a um valor atribuído, como:
    • $a = null;
    • $a = [];
    • $a = 0;
  • as colunas referem-se a operações de comparação, como:
    • $a === null
    • isset($a)
    • empty($a)
    • $a ? true : false

Todos os resultados são booleanos, true é impresso e false é omitido.

Você pode executar os testes você mesmo, verifique esta essência:
https://gist.github.com/mfdj/8165967


Como complemento à discussão do bigbigmassive sobre o que significa NULL , considere o que "a existência de uma variável" realmente significa.

Em muitos idiomas, você deve declarar explicitamente todas as variáveis ​​antes de usá-las ; isso pode determinar seu tipo, mas, mais importante, declara seu escopo . Uma variável "existe" em todo o seu escopo, e em nenhum lugar fora dela - seja uma função inteira ou um único "bloco".

Dentro de seu escopo, uma variável atribui algum significado a um rótulo que você, o programador, escolheu. Fora de seu escopo, esse rótulo não tem sentido (se você usa o mesmo rótulo em um escopo diferente é basicamente irrelevante).

No PHP, as variáveis ​​não precisam ser declaradas - elas ganham vida assim que você precisar delas. Quando você escreve para uma variável pela primeira vez, o PHP aloca uma entrada na memória para aquela variável. Se você ler uma variável que atualmente não possui uma entrada, o PHP considera essa variável como o valor NULL .

No entanto, os detectores automáticos de qualidade de código geralmente o avisarão se você usar uma variável sem "inicializá-la" primeiro. Em primeiro lugar, isso ajuda a detectar erros de digitação, como atribuir a $thingId mas lendo de $thing_id ; mas, em segundo lugar, obriga a considerar o escopo sobre o qual essa variável tem significado, assim como uma declaração faria.

Qualquer código que se importe se uma variável "existe" é parte do escopo dessa variável - tenha sido inicializado ou não, você, como programador, deu a esse rótulo o significado naquele ponto do código. Como você está usando, deve, de alguma forma, "existir" e, se existir, deve ter um valor implícito; no PHP, esse valor implícito é null .

Por causa da maneira como o PHP funciona, é possível escrever código que trate o namespace de variáveis ​​existentes não como um escopo de rótulos para os quais você deu significado, mas como algum tipo de armazenamento de valor-chave. Você pode, por exemplo, executar código como este: $var = $_GET['var_name']; $$var = $_GET['var_value']; $var = $_GET['var_name']; $$var = $_GET['var_value']; . Só porque você pode, não significa que seja uma boa ideia.

Acontece que o PHP tem uma maneira muito melhor de representar armazenamentos de valor-chave, chamados matrizes associativas. E, embora os valores de uma matriz possam ser tratados como variáveis, você também pode executar operações na matriz como um todo. Se você tiver uma matriz associativa, poderá testar se ela contém uma chave usando array_key_exists() .

Você também pode usar objetos de maneira semelhante, definindo propriedades dinamicamente, caso em que você pode usar property_exists() exatamente da mesma maneira. Obviamente, se você definir uma classe, poderá declarar quais propriedades ela possui - você pode até escolher entre escopo public , private e protected .

Embora haja uma diferença técnica entre uma variável (em oposição a uma chave de matriz ou uma propriedade de objeto) que não tenha sido inicializada (ou que tenha sido explicitamente unset() ) e uma cujo valor seja null , qualquer código que considere isso A diferença de ser significativo é usar as variáveis ​​de uma maneira que elas não devem ser usadas.


Se a variável que você está verificando estiver no escopo global, você poderia fazer:

array_key_exists('v', $GLOBALS) 

Você pode usar a construção de linguagem compacta para testar a existência de uma variável nula. Variáveis ​​que não existem não aparecerão no resultado, enquanto valores nulos aparecerão.

$x = null;
$y = 'y';

$r = compact('x', 'y', 'z');
print_r($r);

// Output:
// Array ( 
//  [x] => 
//  [y] => y 
// ) 

No caso do seu exemplo:

if (compact('v')) {
   // True if $v exists, even when null. 
   // False on var $v; without assignment and when $v does not exist.
}

Claro que para variáveis ​​no escopo global você também pode usar array_key_exists ().

Btw pessoalmente gostaria de evitar situações como a peste onde há uma diferença semântica entre uma variável não existente e a variável com um valor nulo. O PHP e a maioria das outras linguagens simplesmente não acham que existe.


isset verifica se a variável está definida e, em caso afirmativo, se seu valor não é NULL. A última parte é (na minha opinião) não dentro do escopo desta função. Não existe uma solução decente para determinar se uma variável é NULL porque não está definida ou porque está explicitamente definida como NULL .

Aqui está uma solução possível:

$e1 = error_get_last();
$isNULL = is_null(@$x);
$e2 = error_get_last();
$isNOTSET = $e1 != $e2;
echo sprintf("isNOTSET: %d, isNULL: %d", $isNOTSET, $isNULL);

// Sample output:
// when $x is not set: isNOTSET: 1, isNULL: 1
// when $x = NULL:     isNOTSET: 0, isNULL: 1
// when $x = false:    isNOTSET: 0, isNULL: 0

Outra solução alternativa é investigar a saída de get_defined_vars() :

$vars = get_defined_vars();
$isNOTSET = !array_key_exists("x", $vars);
$isNULL = $isNOTSET ? true : is_null($x);
echo sprintf("isNOTSET: %d, isNULL: %d", $isNOTSET, $isNULL);

// Sample output:
// when $x is not set: isNOTSET: 1, isNULL: 1
// when $x = NULL:     isNOTSET: 0, isNULL: 1
// when $x = false:    isNOTSET: 0, isNULL: 0

Eu prefiro não usar vazio como o melhor método para verificar a existência de uma variável que a) existe, eb) não é nulo.

if (!empty($variable)) do_something();

Se eu executar o seguinte:

echo '<?php echo $foo; ?>' | php

Eu recebo um erro:

PHP Notice:  Undefined variable: foo in /home/altern8/- on line 1

Se eu executar o seguinte:

echo '<?php if ( isset($foo) ) { echo $foo; } ?>' | php

Eu não entendo o erro.

Se eu tenho uma variável que deve ser definida, geralmente faço algo como o seguinte.

$foo = isset($foo) ? $foo : null;

ou

if ( ! isset($foo) ) $foo = null;

Dessa forma, mais adiante no script, posso usar $ foo com segurança e saber que "está definido" e que o padrão é null. Mais tarde eu posso if ( is_null($foo) ) { /* ... */ }se eu precisar e saber com certeza que a variável existe, mesmo que seja nula.

A documentação completa do isset lê um pouco mais do que apenas o que foi inicialmente colado. Sim, retorna false para uma variável que foi definida anteriormente, mas agora é nula, mas também retorna false se uma variável ainda não tiver sido definida (ever) e para qualquer variável que tenha sido marcada como indefinida. Ele também observa que o byte NULL ("\ 0") não é considerado nulo e retornará true.

Determine se uma variável está definida.

Se uma variável não foi definida com unset (), ela não será mais definida. isset () retornará FALSE se estiver testando uma variável que tenha sido definida como NULL. Observe também que um byte NULL ("\ 0") não é equivalente à constante PHP NULL.


A única maneira de saber se uma variável é definida no escopo atual ( $GLOBALSnão é confiável) é array_key_exists( 'var_name', get_defined_vars() ).


Acho que a única solução completa é relatar avisos com

error_reporting(E_ALL); // Enables E_NOTICE

Mas você terá que corrigir todos os avisos gerados por variáveis ​​indefinidas, constantes, chaves de matriz, propriedades de classe, entre outros. Depois de ter feito isso, você não terá que se preocupar com a diferença entre variáveis ​​nulas e não declaradas, e a ambiguidade desaparece.

Ativar o relatório de avisos pode não ser uma boa alternativa em todas as situações, mas há boas razões para ativá-lo:

Por que devo corrigir erros E_NOTICE?

No meu caso foi mais de um ano trabalhando em um projeto sem ele, mas foi usado para ter cuidado ao declarar variáveis, então foi rápido para a transição.


Eu tenho que dizer em todos os meus anos de programação PHP, eu nunca encontrei um problema com o isset()retorno de false em uma variável nula. OTOH, eu encontrei problemas com a isset()falha em uma entrada de matriz nula - mas array_key_exists()funciona corretamente nesse caso.

Para alguma comparação, o Icon define explicitamente uma variável não usada como retornando, &nullassim você usa o teste is-null em Icon para também verificar se há uma variável não definida. Isso facilita as coisas. Por outro lado, o Visual BASIC tem vários estados para uma variável que não tem um valor (Nulo, Vazio, Nada, ...) e você geralmente precisa verificar mais de um deles. Isso é conhecido por ser uma fonte de erros.


Vou adicionar um rápido dois centavos para isso. Um motivo pelo qual esse problema é confuso é porque esse cenário parece retornar o mesmo resultado com o relatório de erros não completo:

$a = null;
var_dump($a); // NULL
var_dump($b); // NULL

Você poderia deduzir desse resultado que a diferença entre $a = nulle não definir $bnada é nada.

Relatório de erros indiretos:

NULL

Notice: Undefined variable: b in xxx on line n
NULL

Nota: ele emitiu um erro variável indefinido, mas o valor de saída var_dumpainda é NULL.

O PHP obviamente tem uma habilidade interna para distinguir entre uma variável nula e uma variável indefinida. Parece-me que deveria haver uma função interna para verificar isso.

Eu acho que a resposta aceita é boa para a maior parte, mas se eu fosse implementá-la, eu escreveria uma capa para ela. Como mencionado anteriormente nesta resposta , eu tenho que concordar que eu realmente não encontrei uma situação em que isso tenha sido um problema. Eu pareço quase sempre acabar em um cenário onde minhas variáveis ​​são definidas e definidas, ou não são (indefinidas, não definidas, nulas, em branco, etc). Não quer dizer que uma situação como essa não irá ocorrer no futuro, mas como parece ser uma questão bastante singular, não estou surpreso que os desenvolvedores do PHP não tenham se dado ao trabalho de colocar isso em prática.







isset