Überprüfen Sie, ob der Wert isset und null ist

87

Ich muss überprüfen, ob der Wert als irgendetwas definiert ist, einschließlich null. issetbehandelt Nullwerte als undefiniert und gibt zurück false. Nehmen Sie als Beispiel Folgendes:

$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

Beachten Sie, dass dies nicht $bardefiniert ist.

Ich muss eine Bedingung finden, die Folgendes erfüllt:

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

Irgendwelche Ideen?

Tatu Ulmanen
quelle
19
if (isset ($ foo)) // gibt false zurück, ich
bin
in_array ($ key, array_keys ($ _ SESSION)) && is_null ($ _ SESSION [$ key]) Ich habe mich so lange gefragt ..
Jack
1
Dies ist kein normales Verhalten für mich, isset= ist gesetzt?, Ihre Variable ist auf null gesetzt. Ich habe viel Zeit wegen dieser verschwendet ...
Vincent Decaux

Antworten:

83

IIRC können Sie get_defined_vars()dafür verwenden:

$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
Henrik Opel
quelle
+1 Ich wollte die gleiche Funktion vorschlagen und get_defined_varskomme gerne mit dem Umfang zurecht.
Salathe
1
Scheint zu funktionieren, aber ich hatte auf etwas Einfacheres gehofft. Naja. Mal sehen, ob jemand einen Einzeiler finden kann.
Tatu Ulmanen
4
Nun, Sie brauchen keine Vars, also ist es theoretisch eine Zeile "if (array_key_exists ('foo', get_defined_vars ())) {}"
Hannes
Die neuere Antwort von fvn ist möglicherweise ein schnellerer Weg, um eine Variable zu erhalten, die im aktuellen Kontext vorhanden ist, und vermeidet die Kosten für get_defined_vars(): array_key_exists('foo', compact('foo')). Oder schneller, wenn Sie ein globales testen : array_key_exists('foo', $GLOBALS).
ToolmakerSteve
25

Wenn Sie sich mit Objekteigenschaften befassen, die möglicherweise den Wert NULL haben, können Sie Folgendes verwenden: property_exists()anstelle vonisset()

<?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();

?>

Im Gegensatz zu isset () gibt property_exists () TRUE zurück, auch wenn die Eigenschaft den Wert NULL hat.

John Magnolia
quelle
11
Sie können dasselbe für Arrays mit array_key_exists () tun.
Calum
13

Siehe Bester Weg, um die Existenz einer Variablen in PHP zu testen. isset () ist eindeutig defekt

 if( array_key_exists('foo', $GLOBALS) && is_null($foo)) // true & true => true
 if( array_key_exists('bar', $GLOBALS) && is_null($bar)) // false &  => false
Loïc Février
quelle
3
Der von Ihnen angegebene Code funktioniert nur, wenn sich die Variable im globalen Bereich befindet.
Raveline
In der Tat, aber ist es nicht der häufigste Fall? In einer Funktion haben Sie Variablen im globalen Bereich und Argumente (die immer definiert sind). Sie könnten auch Objekteigenschaften haben, aber dann können Sie 'property_exists' verwenden.
Loïc Février
Die Verwendung von $ GLOBALS scheint etwas volatil zu sein. Ich muss einige Tests selbst durchführen, bevor ich dies als funktionierend deklarieren kann.
Tatu Ulmanen
4

Ich habe festgestellt, dass dies compacteine Funktion ist, die nicht gesetzte Variablen ignoriert, aber auf diejenigen wirkt, die auf eingestellt nullsind. Wenn Sie also eine große lokale Symboltabelle haben, kann ich mir vorstellen, dass Sie eine effizientere Lösung für die Überprüfung erhalten können, array_key_exists('foo', get_defined_vars())indem Sie Folgendes verwenden 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

Aktualisieren

Ab PHP 7.3 gibt compact () einen Hinweis für nicht festgelegte Werte, sodass diese Alternative leider nicht mehr gültig ist.

compact () gibt jetzt einen E_NOTICE-Level-Fehler aus, wenn eine bestimmte Zeichenfolge auf eine nicht gesetzte Variable verweist. Früher wurden solche Zeichenfolgen stillschweigend übersprungen.

nzn
quelle
Interessante Alternative. Beachten Sie jedoch, dass es wahrscheinlich langsamer ist als das Aufrufen von array_key_exists in einem vorhandenen Array, z. B. $ GLOBALS, da das Nachschlagen in einer Hash-Tabelle nicht langsamer wird, wenn die Tabelle groß wird und Sie die zusätzliche Arbeit von hinzugefügt haben compact. Trotzdem habe ich es positiv bewertet, weil es in einer Situation nützlich ist: Wenn Sie wissen möchten, ob fooes im aktuellen Kontext existiert , unabhängig davon, woher es stammt - wenn es Ihnen egal ist, ob es lokal oder global ist, möchten Sie nur wissen, ob es vorhanden ist existiert.
ToolmakerSteve
@ToolmakerSteve - Ich bezog mich tatsächlich auf den potenziell erheblichen Aufwand für Anrufe get_defined_vars. Siehe hier .
nzn
1

Der folgende als PHP-Erweiterung geschriebene Code entspricht array_key_exists ($ name, get_defined_vars ()) (dank Henrik und 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;
    }

}
masakielastisch
quelle
0

Sie können is_null und empty anstelle von isset () verwenden. Leer gibt keine Fehlermeldung aus, wenn die Variable nicht vorhanden ist.

Raveline
quelle
Ich benutze is_null. Das Ergebnis ist unabhängig von der isset.
Tatu Ulmanen
Ich habe beim Posten meiner ersten Antwort einen Fehler gemacht: Haben Sie es mit empty () versucht?
Raveline
1
Dies funktioniert nicht für Werte, die nicht leer und nicht NULL sind, wie z. B. FALSE, 0, array () oder "".
Calum
1
Diese Antwort ist falsch. is_nullhat das gleiche Problem wie is_set: Es kann nicht zwischen "nicht gesetzt" und "auf null gesetzt" unterscheiden, was das Problem ist, das OP hat. emptyist noch schlimmer, wie Calum betont.
ToolmakerSteve
0

Hier eine dumme Problemumgehung mit 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
Philippe Gerber
quelle
1
Sieht nicht sehr tragbar aus .. :)
Tatu Ulmanen
-3

is_null($bar)gibt true zurück, da es überhaupt keine Werte hat. Alternativ können Sie verwenden:

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

um zu überprüfen, ob $bardefiniert ist und nur dann true zurückgibt, wenn:

$bar = null;
if(isset($bar) && is_null($bar)) // returns true
Ruel
quelle
Nein, sagte er, das if(isset($bar))gibt falsch wann $bar = null.
Loïc Février
2
Dies übergibt keine anderen Variablen als null (z. B. if $bar = "test").
Tatu Ulmanen
3
Wenn $ bar = null ist, gibt isset () "false" und is_null () true zurück. Falsch und wahr gibt immer falsch.
Bartek Kosa
Diese Antwort ist völlig falsch. Wie OP sagte, isset($bar)wird auch danach false zurückgegeben $bar = null;.
ToolmakerSteve