Controlla se il valore è impostato e null


88

Devo controllare se il valore è definito come qualcosa, incluso null. issetconsidera i valori nulli come non definiti e restituisce false. Prendi il seguente come esempio:

$foo = null;

if(isset($foo)) // returns false
if(isset($bar)) // returns false
if(isset($foo) || is_null($foo)) // returns true
if(isset($bar) || is_null($bar)) // returns true, raises a notice

Nota che $barnon è definito.

Devo trovare una condizione che soddisfi quanto segue:

if(something($bar)) // returns false;
if(something($foo)) // returns true;

Qualche idea?


19
if (isset ($ foo)) // restituisce false, sono caduto dalla sedia, tutti questi anni ...
max4ever

in_array ($ key, array_keys ($ _ SESSION)) && is_null ($ _ SESSION [$ key]) Me lo chiedevo da così tanto tempo ..
Jack

1
Questo non è un comportamento normale per me, isset= è impostato?, La tua variabile è impostata su null. Ho perso molto tempo a causa di questo ...
Vincent Decaux

Risposte:


84

IIRC, puoi usare get_defined_vars()per questo:

$foo = NULL;
$vars = get_defined_vars();
if (array_key_exists('bar', $vars)) {}; // Should evaluate to FALSE
if (array_key_exists('foo', $vars)) {}; // Should evaluate to TRUE

+1 Stavo per suggerire la stessa funzione, get_defined_varsaffronta felicemente l'ambito.
Salathe il

1
Sembra funzionare, ma speravo in qualcosa di più semplice. Oh bene. Vediamo se qualcuno può inventare un one liner.
Tatu Ulmanen,

4
beh, non hai bisogno di vars, quindi in teoria è una riga "if (array_key_exists ('foo', get_defined_vars ())) {}"
Hannes

la risposta più recente di FVN potrebbe essere un modo più rapido per ottenere una variabile che esiste nel contesto attuale, evitando i costi di get_defined_vars(): array_key_exists('foo', compact('foo')). O più veloce, se la prova di un mondiale: array_key_exists('foo', $GLOBALS).
ToolmakerSteve

25

Se hai a che fare con proprietà di oggetti che potrebbero avere un valore NULL puoi usare: property_exists()invece diisset()

<?php

class myClass {
    public $mine;
    private $xpto;
    static protected $test;

    function test() {
        var_dump(property_exists($this, 'xpto')); //true
    }
}

var_dump(property_exists('myClass', 'mine'));   //true
var_dump(property_exists(new myClass, 'mine')); //true
var_dump(property_exists('myClass', 'xpto'));   //true, as of PHP 5.3.0
var_dump(property_exists('myClass', 'bar'));    //false
var_dump(property_exists('myClass', 'test'));   //true, as of PHP 5.3.0
myClass::test();

?>

Al contrario di isset (), property_exists () restituisce TRUE anche se la proprietà ha il valore NULL.


11
Puoi fare lo stesso per gli array con array_key_exists ();
teaqu

14

Vedere Modo migliore per verificare l'esistenza di una variabile in PHP; isset () è chiaramente rotto

 if( array_key_exists('foo', $GLOBALS) && is_null($foo)) // true & true => true
 if( array_key_exists('bar', $GLOBALS) && is_null($bar)) // false &  => false

3
Il codice citato funziona solo se la variabile è nell'ambito globale.
Raveline,

Effettivamente ma non è il caso più frequente? In una funzione avrai variabili con scope e argomenti globali (che sono sempre definiti). Potresti anche avere proprietà oggetto, ma puoi usare 'property_exists'.
Loïc Février,

L'uso di $ GLOBALS sembra un po 'volatile, devo fare alcuni test da solo prima di poter dichiarare che funziona.
Tatu Ulmanen,

4

Ho scoperto che compactè una funzione che ignora le variabili non impostate ma agisce su quelle impostate su null, quindi quando hai una grande tabella di simboli locale immagino che tu possa ottenere una soluzione più efficiente rispetto al controllo array_key_exists('foo', get_defined_vars())utilizzando array_key_exists('foo', compact('foo')):

$foo = null;
echo isset($foo) ? 'true' : 'false'; // false
echo array_key_exists('foo', compact('foo')) ? 'true' : 'false'; // true
echo isset($bar) ? 'true' : 'false'; // false
echo array_key_exists('bar', compact('bar')) ? 'true' : 'false'; // false

Aggiornare

A partire da PHP 7.3 compact () darà un avviso per i valori non impostati, quindi sfortunatamente questa alternativa non è più valida.

compact () ora emette un errore di livello E_NOTICE se una data stringa fa riferimento a una variabile non impostata. In precedenza, tali stringhe venivano saltate silenziosamente.


Alternativa interessante. Ma nota che probabilmente è più lento che chiamare array_key_exists su un array esistente, come $ GLOBALS - perché una ricerca in una tabella hash non diventa più lenta, quando la tabella diventa grande e hai aggiunto il lavoro extra di compact. Tuttavia, l'ho votato positivamente perché è utile in una situazione: se vuoi sapere se fooesiste nel contesto attuale , indipendentemente da dove proviene - se non ti interessa se è locale o globale, vuoi solo sapere se è esiste.
ToolmakerSteve

@ToolmakerSteve - In realtà mi riferivo al sovraccarico potenzialmente significativo della chiamata get_defined_vars. Vedi qui .
nzn

1

Il codice seguente scritto come estensione PHP è equivalente a array_key_exists ($ name, get_defined_vars ()) (grazie a Henrik e Hannes).

// get_defined_vars()
// https://github.com/php/php-src/blob/master/Zend/zend_builtin_functions.c#L1777
// array_key_exists
// https://github.com/php/php-src/blob/master/ext/standard/array.c#L4393

PHP_FUNCTION(is_defined_var)
{

    char *name;
    int name_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
        return;
    }

    if (!EG(active_symbol_table)) {
        zend_rebuild_symbol_table(TSRMLS_C);
    }

    if (zend_symtable_exists(EG(active_symbol_table), name, name_len + 1)) {
        RETURN_TRUE;
    }

}

0

Potresti usare is_null e empty invece di isset (). Vuoto non stampa un messaggio di errore se la variabile non esiste.


Sto usando is_null. Il risultato è lo stesso indipendentemente da isset.
Tatu Ulmanen,

Ho commesso un errore durante la pubblicazione della mia prima risposta: hai provato con empty ()?
Raveline,

1
Questo non funzionerà per i valori che non sono vuoti e non NULL come FALSE, 0, array () o "".
teaqu

1
Questa risposta è sbagliata. is_nullha lo stesso problema di is_set: non può distinguere tra "non impostato" e "impostato su null", che è il problema che ha OP. emptyè anche peggio, come sottolinea Calum.
ToolmakerSteve

0

Ecco qualche stupida soluzione alternativa usando xdebug. ;-)

function is_declared($name) {
    ob_start();
    xdebug_debug_zval($name);
    $content = ob_get_clean();

    return !empty($content);
}

$foo = null;
var_dump(is_declared('foo')); // -> true

$bla = 'bla';
var_dump(is_declared('bla')); // -> true

var_dump(is_declared('bar')); // -> false

1
Non sembra molto portatile .. :)
Tatu Ulmanen

-3

is_null($bar)restituisce vero, poiché non ha alcun valore. In alternativa puoi usare:

if(isset($bar) && is_null($bar)) // returns false

per verificare se $barè definito e restituirà true solo se:

$bar = null;
if(isset($bar) && is_null($bar)) // returns true

No, ha detto che if(isset($bar))dà falso quando $bar = null.
Loïc Février,

2
Questo non passerà altre variabili oltre a null (es. If $bar = "test").
Tatu Ulmanen,

3
Quando $ bar = null isset () restituirà "false" e is_null () restituirà true. Falso e vero dà sempre falso.
Bartek Kosa

Questa risposta è completamente sbagliata. Come detto da OP, isset($bar)restituisce false, anche dopo $bar = null;.
ToolmakerSteve
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.