Der beste Weg, um die Existenz einer Variablen in PHP zu testen; isset () ist eindeutig gebrochen

Aus den isset() :

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

Im Grunde isset() nicht, ob die Variable überhaupt gesetzt ist, sondern ob sie auf irgendetwas außer NULL .

Angesichts dessen, was ist der beste Weg, tatsächlich auf die Existenz einer Variablen zu prüfen? Ich habe versucht, etwas wie:

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

(Das @ ist notwendig, um die Warnung zu vermeiden, wenn $v nicht gesetzt ist), aber is_null() hat ein ähnliches Problem wie isset() : Es gibt TRUE bei nicht gesetzten Variablen zurück! Es scheint auch, dass:

 @($v === NULL) 

funktioniert genau wie @is_null($v) , also auch.

Wie sollen wir zuverlässig auf die Existenz einer Variablen in PHP prüfen?


Edit: Es gibt eindeutig einen Unterschied in PHP zwischen Variablen, die nicht gesetzt sind, und Variablen, die auf NULL :

  NULL); var_dump($a); 

PHP zeigt, dass $a['b'] existiert und einen NULL Wert hat. Wenn Sie hinzufügen:

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

Sie können die Ambiguität, über die ich spreche, mit der function isset() . Hier ist die Ausgabe aller drei var_dump()s :

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

Weiter bearbeiten: zwei Dinge.

Einer, ein Anwendungsfall. Ein Array wird in die Daten einer SQL UPDATE statement umgewandelt, wobei die Schlüssel des Arrays die Spalten der Tabelle sind und die Werte des Arrays die Werte sind, die auf jede Spalte angewendet werden. Jede der Spalten der Tabelle kann einen NULL Wert enthalten, der durch die Übergabe eines NULL Werts im Array angegeben wird. Sie benötigen eine Möglichkeit, um zwischen einem nicht vorhandenen Array-Schlüssel und dem Wert eines Arrays, der auf NULL , zu unterscheiden. Das ist der Unterschied zwischen dem Wert der Spalte nicht zu aktualisieren und den Wert der Spalte auf NULL aktualisieren.

Zweitens, Zoredaches Antwort array_key_exists() funktioniert korrekt für meinen obigen Anwendungsfall und für alle globalen Variablen:

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

Ausgänge:

 bool(true) bool(false) 

Da dies array_key_exists() überall funktioniert, kann ich sehen, dass zwischen Variablen, die nicht existieren, und Variablen, die auf NULL , Unklarheit herrscht. Ich rufe array_key_exists() den einfachsten Weg in PHP auf, um wirklich nach der Existenz von a zu array_key_exists() variabel .

(Nur ein anderer Fall, den ich mir array_key_exists() kann, ist für classneigenschaften, für die es property_exists() , was laut seiner Dokumentation ähnlich wie array_key_exists() funktioniert, da es richtig unterscheidet zwischen nicht gesetzt und auf NULL .)

Solutions Collecting From Web of "Der beste Weg, um die Existenz einer Variablen in PHP zu testen; isset () ist eindeutig gebrochen"

Wenn die zu überprüfende Variable im globalen Gültigkeitsbereich wäre, könnten Sie Folgendes tun:

 array_key_exists('v', $GLOBALS) 

Versuch, einen Überblick über die verschiedenen Diskussionen und Antworten zu geben:

Es gibt keine einzelne Antwort auf die Frage, die alle Wege isset kann, die verwendet werden können. Einige Anwendungsfälle werden von anderen functionen angesprochen, während andere der Überprüfung nicht standhalten oder einen zweifelhaften Wert haben, der über den Code-Golf hinausgeht. Weit davon entfernt, “gebrochen” oder “inkonsistent” zu sein, zeigen andere Anwendungsfälle, warum die Reaktion von null das logische Verhalten von isset ist.

Echte Anwendungsfälle (mit Lösungen)

1. Array-Tasten

Arrays können wie Sammlungen von Variablen behandelt werden, wobei isset und isset sie so behandeln, als wären sie. Da sie jedoch iteriert, gezählt, usw. sein können, ist ein fehlender Wert nicht derselbe wie einer, dessen Wert null .

Die Antwort in diesem Fall ist array_key_exists() anstelle von isset() .

Da dies das zu überprüfende Array als functionsargument benötigt, wird PHP immer noch “Hinweise” auslösen, wenn das Array selbst nicht existiert. In einigen Fällen kann argumentiert werden, dass jede Dimension zuerst initialisiert worden sein sollte, damit die Bekanntmachung ihren Zweck erfüllt. In anderen Fällen würde eine “rekursive” array_key_exists function, die jede Dimension des Arrays der Reihe nach überprüft, dies vermeiden, wäre aber im Grunde dasselbe wie @array_key_exists . Es ist auch etwas tangential zur Handhabung von null .

2. Objekteigenschaften

In der traditionellen Theorie der “objektorientierten Programmierung” sind Verkapselung und Polymorphie Schlüsseleigenschaften von Objekten; In einer klassenbasierten OOP-Implementierung wie PHP werden die eingekapselten Eigenschaften als Teil der classndefinition deklariert und mit Zugriffsebenen ( public , protected oder private ) versehen.

PHP ermöglicht es Ihnen jedoch auch, einem Objekt dynamisch Eigenschaften hinzuzufügen, wie Sie es bei einem Array stdClass würden, und einige Leute verwenden stdClass Objekte (technisch gesehen Instanzen der eingebauten stdClass , die keine Methoden oder private functionalität haben) in einem ähnlich wie assoziative Arrays. Dies führt zu Situationen, in denen eine function wissen möchte, ob eine bestimmte Eigenschaft zu dem ihr übergebenen Objekt hinzugefügt wurde.

Wie bei den Array-Schlüsseln ist eine Lösung zum Überprüfen von Objekteigenschaften in der Sprache enthalten, die vernünftigerweise property_exists .

Nicht zu rechtfertigende Anwendungsfälle mit Diskussion

3. register_globals und andere Verschmutzung des globalen Namensraums

Die register_globals hinzugefügte Variablen zum globalen Bereich, deren Namen durch Aspekte der HTTP-Anfrage bestimmt wurden (GET- und POST-Parameter und Cookies). Dies kann zu errorshaftem und unsicherem Code führen, weshalb dieser standardmäßig seit PHP 4.2, veröffentlicht im August 2000 und vollständig in PHP 5.4, veröffentlicht März 2012, deaktiviert wurde. Es ist jedoch möglich, dass einige Systeme noch mit dieser function aktiviert oder emuliert ausgeführt werden. Es ist auch möglich, den globalen Namespace auf andere Weise zu verschmutzen, indem Sie das global Schlüsselwort oder das $GLOBALS Array verwenden.

Erstens wird register_globals höchstwahrscheinlich nicht unerwartet eine null Variable erzeugen, da die GET-, POST- und Cookie-Werte immer Zeichenfolgen sind (wobei '' immer noch von isset ), und Variablen in der Sitzung sollten vollständig unter der Kontrolle des Programmierers sein.

Zweitens ist die Verschmutzung einer Variablen mit dem Wert null nur dann ein Problem, wenn dadurch eine vorherige Initialisierung überschrieben wird. Das “Überschreiben” einer nicht initialisierten Variablen mit null wäre nur dann problematisch, wenn der Code irgendwo anders zwischen den beiden Zuständen unterscheiden würde, so dass diese Möglichkeit allein ein Argument gegen eine solche Unterscheidung ist.

4. get_defined_vars und compact

Mit einigen selten verwendeten functionen in PHP, wie get_defined_vars und compact , können Sie Variablennamen so behandeln, als wären sie Schlüssel in einem Array. Bei globalen Variablen erlaubt das super-globale Array $GLOBALS einen ähnlichen Zugriff und ist häufiger. Diese Zugriffsmethoden verhalten sich anders, wenn eine Variable nicht im relevanten Bereich definiert ist.

Sobald Sie entschieden haben, eine Gruppe von Variablen als Array mit einem dieser Mechanismen zu behandeln, können Sie dieselben Operationen ausführen wie in jedem normalen Array. Siehe dazu 1.

functionalität, die nur existierte, um vorherzusagen, wie sich diese functionen verhalten werden (zB “wird es einen Schlüssel geben” foo ‘in dem von get_defined_vars zurückgegebenen get_defined_vars ?) get_defined_vars überflüssig, da Sie die function einfach ausführen und ohne negative Auswirkungen herausfinden können .

4a. Variable Variablen ( $$foo )

Sie sind zwar nicht ganz die gleichen wie functionen, die einen Satz von Variablen in ein assoziatives Array umwandeln, aber die meisten Fälle mit “Variablenvariablen” (“einer Variablen basierend auf dieser anderen Variablen zuweisen”) können und sollten stattdessen ein assoziatives Array verwenden .

Ein Variablenname ist im Prinzip die Bezeichnung, die einem Programmierer vom Wert gegeben wird. Wenn Sie es zur Laufzeit ermitteln, handelt es sich nicht wirklich um eine Bezeichnung, sondern um einen Schlüssel in einem Schlüsselwertspeicher. Praktischerweise verlieren Sie, indem Sie kein Array verwenden, die Fähigkeit zu zählen, zu iterieren usw .; es kann auch unmöglich werden, eine Variable “außerhalb” des Schlüsselwertspeichers zu haben, da sie möglicherweise von $$foo .

Sobald der Code für die Verwendung eines assoziativen Arrays geändert wurde, ist er für Lösung 1 zugänglich. Der Zugriff auf indirekte Objekteigenschaften (z. B. $foo->$property_name ) kann mit Lösung 2 erfolgen.

5. isset ist so viel einfacher zu array_key_exists als array_key_exists

Ich bin mir nicht sicher, ob das wirklich relevant ist, aber ja, PHP-functionsnamen können manchmal ziemlich langatmig und inkonsistent sein. Anscheinend verwendeten prähistorische Versionen von PHP die Länge eines functionsnamens als Hash-Schlüssel, also hat Rasmus absichtlich functionsnamen wie htmlspecialchars so dass sie eine ungewöhnliche Anzahl von Zeichen hätten …

Zumindest schreiben wir nicht Java, oder? 😉

6. Nicht initialisierte Variablen haben einen Typ

Die Manpage zu Variablengrundlagen enthält diese Aussage:

Nicht initialisierte Variablen haben einen Standardwert ihres Typs, abhängig vom Kontext, in dem sie verwendet werden

Ich bin mir nicht sicher, ob es in der Zend Engine eine Vorstellung von “nicht initialisierter aber bekannter Art” gibt oder ob das zu viel in die Aussage hineinliest.

Es ist klar, dass es für ihr Verhalten keinen praktischen Unterschied macht, da die auf dieser Seite beschriebenen Verhaltensweisen für nicht initialisierte Variablen mit dem Verhalten einer Variablen identisch sind, deren Wert null . Um ein Beispiel zu wählen, enden sowohl $a als auch $b in diesem Code als Integer 42 :

 unset($a); $a += 42; $b = null; $b += 42; 

(Der erste wird eine Meldung über eine nicht deklarierte Variable auslösen, um einen besseren Code zu schreiben, aber es macht keinen Unterschied, wie der Code tatsächlich ausgeführt wird.)

99. Erkennen, ob eine function ausgeführt wurde

(Behalte dies als letztes, da es viel länger ist als die anderen. Vielleicht werde ich es später bearbeiten …)

Betrachten Sie den folgenden Code:

 $test_value = 'hello'; foreach ( $list_of_things as $thing ) { if ( some_test($thing, $test_value) ) { $result = some_function($thing); } } if ( isset($result) ) { echo 'The test passed at least once!'; } 

Wenn some_function null some_function kann, besteht die Möglichkeit, dass das echo nicht erreicht wird, obwohl some_test true . Die Absicht des Programmierers war herauszufinden, wann $result niemals gesetzt wurde, aber PHP erlaubt dies nicht.

Es gibt jedoch andere Probleme mit diesem Ansatz, die deutlich werden, wenn Sie eine äußere Schleife hinzufügen:

 foreach ( $list_of_tests as $test_value ) { // something's missing here... foreach ( $list_of_things as $thing ) { if ( some_test($thing, $test_value) ) { $result = some_function($thing); } } if ( isset($result) ) { echo 'The test passed at least once!'; } } 

Da $result niemals explizit initialisiert wird, nimmt es einen Wert an, wenn der allererste Test erfolgreich ist. $result ist es unmöglich zu sagen, ob nachfolgende Tests erfolgreich waren oder nicht. Dies ist ein extrem häufiger Fehler, wenn Variablen nicht richtig initialisiert werden.

Um das zu beheben, müssen wir etwas in der Zeile tun, wo ich bemerkt habe, dass etwas fehlt. Die offensichtlichste Lösung besteht darin, $result auf einen “terminal value” zu setzen, den some_function niemals zurückgeben kann. Wenn dies null , wird der Rest des Codes gut funktionieren. Wenn es keinen natürlichen Kandidaten für einen Terminal-Wert gibt, weil some_function einen extrem unvorhersagbaren Rückgabetyp hat (was wahrscheinlich ein schlechtes Zeichen an sich ist), könnte stattdessen ein zusätzlicher boolescher Wert, z. B. $found , verwendet werden.

Gedankenexperiment eins: die Konstante very_null

PHP könnte theoretisch eine spezielle Konstante – ebenso wie null – für die Verwendung als Endwert bereitstellen; vermutlich wäre es illegal, dies von einer function zurückzugeben, oder es würde auf null , und dasselbe würde wahrscheinlich gelten, wenn man es als functionsargument eingibt. Das würde diesen sehr speziellen Fall etwas einfacher machen, aber sobald Sie sich entschieden haben, den Code neu zu faktorisieren – zum Beispiel, um die innere Schleife in eine separate function zu bringen – würde sie nutzlos werden. Wenn die Konstante zwischen functionen übergeben werden kann, können Sie nicht garantieren, dass some_function sie nicht some_function , so dass sie als universeller Terminalwert nicht mehr nützlich wäre.

Das Argument für das Auffinden von nicht initialisierten Variablen in diesem Fall läuft auf das Argument für diese spezielle Konstante hinaus: Wenn Sie den Kommentar durch unset($result) ersetzen und das anders behandeln als $result = null , führen Sie einen “Wert” für $result , das nicht weitergegeben werden kann und nur von bestimmten integrierten functionen erkannt werden kann.

Gedankenexperiment zwei: Zuweisungszähler

Eine andere Art zu denken, was das letzte ist, if man fragt: ” if irgendwas eine Zuweisung zu $result ?” Anstatt es als einen speziellen Wert von $result , könnte man es sich vielleicht als “Metadaten” über die Variable vorstellen, ein bisschen wie Perls “variable tainting”. Anstatt also zu isset , könnten Sie es has_been_assigned_to , und nicht reset_assignment_state .

Aber wenn ja, warum bei einem Boolean stoppen? Was ist, wenn Sie wissen möchten, wie oft der Test bestanden hat? Sie könnten einfach Ihre Metadaten auf eine Ganzzahl erweitern und get_assignment_count und reset_assignment_count

Offensichtlich würde die Hinzufügung eines solchen Merkmals einen Kompromiss in Bezug auf Komplexität und performance der Sprache darstellen, so dass es sorgfältig abgewogen werden müsste gegenüber seiner erwarteten Nützlichkeit. Wie bei einer very_null konstanten very_null wäre sie nur unter sehr engen Bedingungen nützlich und wäre ähnlich resistent gegenüber einer erneuten Faktorisierung.

Die hoffentlich naheliegende Frage ist, warum die PHP-Runtime-Engine im Voraus davon ausgehen sollte, dass Sie solche Dinge im Auge behalten wollen, anstatt sie mit normalem Code explizit auszuführen.

Manchmal bekomme ich ein wenig verloren, wenn ich versuche herauszufinden, welche Vergleichsoperation in einer bestimmten Situation verwendet werden soll. isset() gilt nur für nicht initialisierte oder explizit Nullwerte. Das Übergeben / Zuweisen von Null ist eine gute Möglichkeit, sicherzustellen, dass ein logischer Vergleich wie erwartet funktioniert.

Dennoch ist es ein wenig schwierig, darüber nachzudenken, also ist hier eine einfache Matrix, die vergleicht, wie verschiedene Werte von verschiedenen Operationen ausgewertet werden:

 | | ===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 | 

Um die Tabelle anzupassen, habe ich die Beschriftungen etwas komprimiert:

  • $a; bezieht sich auf eine deklarierte, aber nicht zugewiesene Variable
  • Alles andere in der ersten Spalte bezieht sich auf einen zugewiesenen Wert wie:
    • $a = null;
    • $a = [];
    • $a = 0;
  • Die Spalten beziehen sich auf Vergleichsoperationen wie:
    • $a === null
    • isset($a)
    • empty($a)
    • $a ? true : false

Alle Ergebnisse sind boolesch, true wird gedruckt und false wird weggelassen.

Sie können die Tests selbst ausführen, überprüfen Sie diesen Gedanken:
https://gist.github.com/mfdj/8165967

Sie können das kompakte Sprachkonstrukt verwenden, um das Vorhandensein einer Nullvariablen zu testen. Variablen, die nicht vorhanden sind, werden im Ergebnis nicht angezeigt, während Nullwerte angezeigt werden.

 $x = null; $y = 'y'; $r = compact('x', 'y', 'z'); print_r($r); // Output: // Array ( // [x] => // [y] => y // ) 

Im Falle Ihres Beispiels:

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

Natürlich können Sie für Variablen im globalen Gültigkeitsbereich auch array_key_exists () verwenden.

Übrigens würde ich Situationen wie die Pest vermeiden, wo es einen semantischen Unterschied zwischen einer nicht existierenden Variable und der Variablen mit einem Nullwert gibt. PHP und die meisten anderen Sprachen glauben einfach nicht, dass es da ist.

NULL erklären, logisch denken

Ich denke, die offensichtliche Antwort auf all das ist … Initialisiere deine Variablen nicht als NULL, initialisiere sie als etwas, das relevant ist für das, was sie werden sollen.

Behandle NULL richtig

NULL sollte als “nicht existierender Wert” behandelt werden, was die Bedeutung von NULL ist. Die Variable kann nicht als in PHP vorhanden klassifiziert werden, da nicht bekannt ist, um welchen Typ von Entität es sich handelt. Es kann auch nicht existieren, also sagt PHP einfach “Gut, es tut es nicht, weil es sowieso keinen Sinn hat und NULL ist meine Art das zu sagen”.

Ein Argument

Lass uns jetzt streiten. “Aber NULL ist wie 0 oder FALSE oder ” zu sagen.

Falsch, 0-FALSCH- ” werden immer noch als leere Werte klassifiziert, aber sie werden als eine Art von Wert oder eine vordefinierte Antwort auf eine Frage angegeben. FALSE ist die Antwort auf Ja oder Nein, “” ist die Antwort auf den von jemandem übermittelten Titel, und 0 ist die Antwort auf Menge oder Zeit usw. Sie werden als eine Art von Antwort / Ergebnis gesetzt, die sie als gesetzt setzt.

NULL ist einfach keine Antwort was auch immer, es sagt uns nicht Ja oder Nein und es sagt uns nicht die Zeit und es sagt uns nicht, dass eine leere Zeichenfolge eingereicht wurde. Das ist die Grundlogik für das Verständnis von NULL.

Zusammenfassung

Es geht nicht darum, verrückte functionen zu kreieren, um das Problem zu umgehen, es verändert nur die Art, wie dein Gehirn NULL betrachtet. Wenn es NULL ist, nehme an, dass es nicht als irgendetwas festgelegt ist. Wenn Sie Variablen vordefinieren, dann definieren Sie sie als 0, FALSCH oder “” abhängig von der Art der Verwendung, die Sie für sie beabsichtigen.

Fühlen Sie sich frei, dies zu zitieren. Es ist von der Spitze meines logischen Kopfes 🙂

Objekteigenschaften können von property_exists auf Existenz überprüft werden

Beispiel aus einem Komponententest:

 function testPropertiesExist() { $sl =& $this->system_log; $props = array('log_id', 'type', 'message', 'username', 'ip_address', 'date_added'); foreach($props as $prop) { $this->assertTrue(property_exists($sl, $prop), "Property < {$prop}> exists"); } } 

Als Ergänzung zur Diskussion von bigbigmassive darüber, was NULL bedeutet , bedenke , was “die Existenz einer Variablen” tatsächlich bedeutet.

In vielen Sprachen müssen Sie jede Variable explizit deklarieren, bevor Sie sie verwenden . dies kann seinen Typ bestimmen, aber noch wichtiger, es erklärt seinen scope . Eine Variable “existiert” überall in ihrem scope und nirgendwo außerhalb – sei es eine ganze function oder ein einzelner “Block”.

In ihrem Gültigkeitsbereich weist eine Variable einem Etikett eine Bedeutung zu, die Sie, der Programmierer, gewählt haben. Außerhalb seines Geltungsbereichs ist dieses Label bedeutungslos (ob Sie dasselbe Label in einem anderen Bereich verwenden, ist im Grunde irrelevant).

In PHP müssen Variablen nicht deklariert werden – sie werden lebendig, sobald Sie sie brauchen. Wenn Sie zum ersten Mal in eine Variable schreiben, ordnet PHP einen Eintrag im Speicher für diese Variable zu. Wenn Sie von einer Variablen lesen, die momentan keinen Eintrag enthält, betrachtet PHP diese Variable als den Wert NULL .

Automatische Codequalitätsdetektoren warnen Sie jedoch in der Regel, wenn Sie eine Variable verwenden, ohne sie vorher zu initialisieren. Erstens hilft dies, Tipperrors zu erkennen, wie zum Beispiel $thingId aber von $thing_id ; Aber zweitens zwingt es Sie dazu, den scope zu berücksichtigen, über den diese Variable eine Bedeutung hat, so wie es eine Erklärung wäre.

Jeder Code, der darauf achtet, ob eine Variable “exists” ist, ist Teil des Gültigkeitsbereichs dieser Variablen – unabhängig davon, ob sie initialisiert wurde oder nicht, haben Sie als Programmierer diese Label-Bedeutung an diesem Punkt des Codes angegeben. Da Sie es verwenden, muss es in gewissem Sinne “existieren”, und wenn es existiert, muss es einen impliziten Wert haben; In PHP ist dieser implizite Wert null .

Aufgrund der functionsweise von PHP ist es möglich, Code zu schreiben, der den Namespace existierender Variablen nicht als einen Bereich von Labels behandelt, die Sie als sinnvoll erachtet haben, sondern als eine Art Schlüssel-Wert-Speicher. Sie können beispielsweise folgenden Code ausführen: $var = $_GET['var_name']; $$var = $_GET['var_value']; $var = $_GET['var_name']; $$var = $_GET['var_value']; . Nur weil du kannst, bedeutet das nicht, dass es eine gute Idee ist.

Es stellt sich heraus, dass PHP einen viel besseren Weg hat, Schlüssel-Wert-Speicher, assoziative Arrays genannt, darzustellen. Und obwohl die Werte eines Arrays wie Variablen behandelt werden können, können Sie auch Operationen für das Array als Ganzes durchführen. Wenn Sie ein assoziatives Array haben, können Sie mithilfe von array_key_exists() testen, ob es einen Schlüssel enthält.

Sie können Objekte auch auf ähnliche Weise verwenden und Eigenschaften dynamisch festlegen. In diesem Fall können Sie property_exists() genauso verwenden. Wenn Sie eine class definieren, können Sie natürlich angeben, welche Eigenschaften sie haben – Sie können sogar zwischen public , private und protected Bereich wählen.

Es gibt zwar einen technischen Unterschied zwischen einer Variablen (im Gegensatz zu einem Array-Schlüssel oder einer Objekteigenschaft), die nicht initialisiert wurde (oder die explizit unset() ), und einem anderen, dessen Wert null ist Unterschied, um sinnvoll zu sein, ist die Verwendung von Variablen in einer Weise, dass sie nicht verwendet werden sollen.

isset prüft, ob die Variable gesetzt ist, und wenn ja, ob ihr Wert nicht NULL ist. Der letzte Teil ist (meiner Meinung nach) nicht im Rahmen dieser function. Es gibt keine angemessene Problemumgehung, um festzustellen, ob eine Variable NULL ist, weil es nicht festgelegt ist oder weil es explizit auf NULL festgelegt ist .

Hier ist eine mögliche Lösung:

 $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 

Eine andere Problemumgehung besteht darin, die Ausgabe von 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 

Ich stimme deiner Argumentation über NULL nicht zu , und zu sagen, dass du deine Denkweise über NULL ändern musst, ist einfach komisch.

Ich denke, dass isset () nicht richtig entworfen wurde, sollte iset () Ihnen sagen, wenn die Variable gesetzt worden ist und es sollte sich nicht mit dem tatsächlichen Wert der Variable befassen.

Was ist, wenn Sie Werte überprüfen, die von einer database zurückgegeben werden, und eine der Spalten einen NULL-Wert hat, möchten Sie immer noch wissen, ob es existiert, selbst wenn der Wert NULL ist … nichte nicht hier auf isset ().

Gleichfalls

 $a = array ('test' => 1, 'hello' => NULL); var_dump(isset($a['test'])); // TRUE var_dump(isset($a['foo'])); // FALSE var_dump(isset($a['hello'])); // FALSE 

isset () sollte so aussehen:

 if(isset($var) && $var===NULL){.... 

Auf diese Weise überlassen wir es dem Programmierer, die Typen zu überprüfen und es nicht an isset () zu übergeben, damit es nicht da ist, weil der Wert NULL ist – sein dummes Design

I’m going to add a quick two cents to this. One reason this issue is confusing is because this scenario seems to return the same result with error reporting not on full:

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

You could assume from this result that the difference between $a = null and not defining $b at all is nothing.

Crank error reporting up:

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

Note: it threw an undefined variable error, but the output value of var_dump is still NULL .

PHP obviously does have an internal ability to distinguish between a null variable and an undefined variable. It seems to me that there should be a built in function to check for this.

I think the accepted answer is good for the most part, but if I was going to implement it I would write a wrapper for it. As previously mentioned in this answer , I have to agree that I haven’t actually encountered a situation where this has been a problem. I seem to almost always end up in a scenario where my variables are either set and defined, or they aren’t (undefined, unset, null, blank, etc). Not to say that a situation like this won’t occur in future, but as it seems to be quite a unique issue I’m not surprised that the PHP devs haven’t bothered to put this in.

If I run the following:

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

Ich erhalte einen Fehler:

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

If I run the following:

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

I do not get the error.

If I have a variable that should be set, I usually do something like the following.

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

oder

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

That way, later in the script, I can safely use $foo and know that it “is set”, and that it defaults to null. Later I can if ( is_null($foo) ) { /* ... */ } if I need to and know for certain that the variable exists, even if it is null.

The full isset documentation reads a little more than just what was initially pasted. Yes, it returns false for a variable that was previously set but is now null, but it also returns false if a variable has not yet been set (ever) and for any variable that has been marked as unset. It also notes that the NULL byte (“\0”) is not considered null and will return true.

Determine whether a variable is set.

If a variable has been unset with unset(), it will no longer be set. isset() will return FALSE if testing a variable that has been set to NULL. Also note that a NULL byte (“\0”) is not equivalent to the PHP NULL constant.

Versuchen Sie es mit

 unset($v) 

It seems the only time a variable is not set is when it is specifically unset($v). It sounds like your meaning of ‘existence’ is different than PHP’s definition. NULL is certainly existing, it is NULL.

I have to say in all my years of PHP programming, I have never encountered a problem with isset() returning false on a null variable. OTOH, I have encountered problems with isset() failing on a null array entry – but array_key_exists() works correctly in that case.

For some comparison, Icon explicitly defines an unused variable as returning &null so you use the is-null test in Icon to also check for an unset variable. This does make things easier. On the other hand, Visual BASIC has multiple states for a variable that doesn’t have a value (Null, Empty, Nothing, …), and you often have to check for more than one of them. This is known to be a source of bugs.

According to the PHP Manual for the empty() function, “Determine whether a variable is considered to be empty. A variable is considered empty IF IT DOES NOT EXIST or if its value equals FALSE. empty() does not generate a warning if the variable does not exist.” (My emphasis.) That means the empty() function should qualify as the “best way to test a variable’s existence in PHP”, per the title Question.

However, this is not good enough, because the empty() function can be fooled by a variable that does exist and is set to NULL.

I’m interrupting my earlier answer to present something better, because it is less cumbersome than my original answer (which follows this interruption, for comparing).

  function undef($dnc) //do not care what we receive { $inf=ob_get_contents(); //get the content of the buffer ob_end_clean(); //stop buffering outputs, and empty the buffer if($inf>"") //if test associated with the call to this function had an output { if(false!==strpos($inf, "Undef"); //if the word "Undefined" was part of the output return true; //tested variable is undefined } return false; //tested variable is not undefined } 

Two simple lines of code can use the above function to reveal if a variable is undefined:

  ob_start(); //pass all output messages (including errors) to a buffer if(undef($testvar===null)) //in this case the variable being tested is $testvar 

You can follow those two lines with anything appropriate, such as this example:

  echo("variable is undefined"); else echo("variable exists, holding some value"); 

I wanted to put the call to ob_start() and the ($testvar===null) inside the function, and simply pass the variable to the function, but it doesn’t work. Even if you try to use “pass by reference” of the variable to the function, the variable BECOMES defined, and then the function can never detect that it previously had been undefined. What is presented here is a compromise between what I wanted to do, and what actually works.

The preceding implies that there is another way to always avoid running into the “Undefined variable” error message. (The assumption here is, preventing such a message is why you want to test to see if a variable is undefined.)

  function inst(&$v) { return; } //receive any variable passed by reference; instantiates the undefined 

Just call that function before doing something to your $testvar:

  inst($testvar); //The function doesn't affect any value of any already-existing variable 

The newly-instantiated variable’s value is set to null, of course!

(Interruption ends)

So, after some studying and experimenting, here is something guaranteed to work:

  function myHndlr($en, $es, $ef, $el) { global $er; $er = (substr($es, 0, 18) == "Undefined variable"); return; } $er = false; if(empty($testvar)) { set_error_handler("myHndlr"); ($testvar === null); restore_error_handler(); } if($er) // will be 1 (true) if the tested variable was not defined. { ; //do whatever you think is appropriate to the undefined variable } 

The explanation: A variable $er is initialized to a default value of “no error”. A “handler function” is defined. If the $testvar (the variable we want to know whether or not is undefined) passes the preliminary empty() function test, then we do the more thorough test. We call the set_error_handler() function to use the previously-defined handler function. Then we do a simple identity-comparison involving $testvar, WHICH IF UNDEFINED WILL TRIGGER AN ERROR. The handler function captures the error and specifically tests to see if the reason for the error is the fact that the variable is undefined. The result is placed in the error-information variable $er, which we can later test to do whatever we want as a result of knowing for sure whether or not $testvar was defined. Because we only need the handler function for this limited purpose, we restore the original error-handling function. The “myHndlr” function only needs to be declared once; the other code can be copied to whatever places are appropriate, for $testvar or any other variable we want to test this way.

I think the only full solution is to report notices with

 error_reporting(E_ALL); // Enables E_NOTICE 

But you will have to fix all the notices generated by undefined variables, constants, array keys, class properties amongst others. Once you have done that you won’t have to worry about the difference between null and not declared variables, and the ambiguity dissappears.

Enabling notice reporting might not be a good alternative in all situations, but there are good reasons to enable it:

Why should I fix E_NOTICE errors?

In my case was more than a year working in a proyect without it, but was used to be careful about declaring variables, so it was fast to transition.

THE only way to know if a variable is defined in current scope ( $GLOBALS is not trustworthy) is array_key_exists( 'var_name', get_defined_vars() ) .

I prefer using not empty as the best method to check for the existence of a variable that a) exists, and b) is not null.

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