2010-09-27 16 views
65

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

$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 $bar nicht definiert ist.

Ich brauche einen Zustand zu finden, die die folgenden erfüllt:

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

Irgendwelche Ideen?

+14

if (isset ($ foo)) // false zurückgibt, i den Stuhl fiel, all die Jahre ... – max4ever

Antwort

63

IIRC, können Sie get_defined_vars() für diesen Einsatz:

$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 
+0

+1 Ich wollte die gleiche Funktion vorschlagen, 'get_defined_vars' bewältigt glücklich den Umfang. – salathe

+1

Scheint zu arbeiten, aber ich habe auf etwas einfacheres gehofft. Naja. Mal sehen, ob irgendjemand mit einem Liner kommen kann. –

+4

Nun, Sie brauchen nicht vars, also theoretisch eine Zeile "if (array_key_exists ('foo', get_defined_vars())) {}" – Hannes

0

Sie is_null und empty statt isset nutzen könnten(). Leer gibt keine Fehlermeldung aus, wenn die Variable nicht existiert.

+0

ich is_null verwende. Das Ergebnis ist das gleiche, unabhängig von der Assets. –

+0

Ich habe einen Fehler gemacht, während ich meine erste Antwort gepostet habe: hast du es mit leer() versucht? – Raveline

+0

Dies funktioniert nicht für Werte, die nicht leer sind und nicht NULL wie FALSE, 0, array() oder "". – C9HDN

12

Siehe Best way to test for a variable's existence in PHP; isset() is clearly broken

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

Der angegebene Code funktioniert nur, wenn die Variable im globalen Gültigkeitsbereich liegt. – Raveline

+0

In der Tat, aber ist es nicht der häufigste Fall? In einer Funktion haben Sie Variablen im globalen Gültigkeitsbereich und Argumente (die immer definiert sind). Sie könnten auch Objekteigenschaften haben, aber dann können Sie 'property_exists' verwenden. –

+0

Die Verwendung von $ GLOBALS scheint ein wenig unbeständig zu sein, ich muss mich selbst testen, bevor ich dies als funktionierend bezeichnen kann. –

-2

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

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

zu überprüfen, ob $bar definiert und wird nur wahr zurück, wenn:

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

Nein, er sagte, dass 'if (isset ($ bar))' falsch gibt, wenn $ bar = null ist. –

+0

mein schlechtes. wird meine Antwort aktualisieren. – Ruel

+2

Dies wird keine anderen Variablen als null übergeben (zB wenn '$ bar =" test "'). –

0

Hier einige dumme Abhilfe xdebug verwenden. ;-)

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

Sieht nicht sehr portabel .. :) –

+1

In der Tat. Und die Leistung kann ebenfalls sinken. ;-) –

1

Der folgende Code als PHP-Erweiterung geschrieben 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; 
    } 

} 
21

Wenn Sie mit Objekteigenschaften handelt Whcih einen Wert von NULL haben könnten Sie verwenden können: property_exists() statt isset()

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

?> 

Wie isset gegen(), property_exists() liefert TRUE auch wenn die Eigenschaft den Wert NULL hat.

+7

Sie können das gleiche für Arrays mit array_key_exists(); – C9HDN

2

Ich habe festgestellt, dass compact eine Funktion ist, die nicht gesetzt Variablen ignoriert, sondern auf diejenigen null gesetzt wirkt, so, wenn Sie eine große lokale Symboltabelle haben würde ich mir vorstellen, eine effizientere Lösung über die Überprüfung array_key_exists('foo', get_defined_vars()) bekommen kann mit 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 
+0

Interessante Alternative. Beachten Sie jedoch, dass es wahrscheinlich * langsamer * ist, als array_key_exists in einem vorhandenen Array wie $ GLOBALS aufzurufen - weil ein Lookup in einer Hash-Tabelle nicht langsamer wird, wenn die Tabelle groß wird und Sie die zusätzliche Arbeit hinzugefügt haben von 'kompakt'. Nichtsdestoweniger habe ich es upvoted, weil es in einer Situation nützlich ist: wenn du wissen willst, ob 'foo' im aktuellen Kontext * existiert, egal woher es kommt - wenn es dir egal ist, ob es lokal oder global ist, einfach möchte wissen, ob es existiert. – ToolmakerSteve

+0

@ToolmakerSteve - Ich bezog mich tatsächlich auf den möglicherweise erheblichen Overhead des Aufrufs von 'get_defined_vars'. Siehe [hier] (http://stackoverflow.com/questions/27808704/what-is-the-performance-impact-off-get-defined-vars). – nzn

Verwandte Themen