Aus den isset()
-Dokumenten :
isset() will return FALSE if testing a variable that has been set to NULL.
Grundsätzlich prüft isset()
nicht, ob die Variable überhaupt gesetzt ist, sondern ob sie auf etwas anderes als NULL
gesetzt ist.
Wie kann man am besten prüfen, ob eine Variable existiert? Ich habe so etwas ausprobiert:
if(isset($v) || @is_null($v))
(Der @
ist notwendig, um die Warnung zu vermeiden, wenn $v
nicht gesetzt ist.) is_null()
hat jedoch ein ähnliches Problem wie isset()
: es gibt TRUE
für unset-Variablen zurück! Es scheint auch so zu sein:
@($v === NULL)
funktioniert genau wie @is_null($v)
, also auch das ist raus.
Wie sollen wir zuverlässig prüfen, ob eine Variable in PHP existiert?
Edit: Es gibt einen klaren Unterschied in PHP zwischen Variablen, die nicht gesetzt sind, und Variablen, die auf NULL
gesetzt sind:
<?php
$a = array('b' => 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 Mehrdeutigkeit sehen, von der ich mit der Funktion isset()
spreche. Hier ist die Ausgabe aller drei dieser var_dump()s
:
array(1) {
["b"]=>
NULL
}
bool(false)
bool(false)
Weitere Bearbeitung: zwei Dinge.
Eins, ein Anwendungsfall. Ein Array wird in die Daten einer SQL UPDATE
-Anweisung umgewandelt, wobei die Schlüssel des Arrays die Spalten der Tabelle sind und die Werte des Arrays die Werte, die auf jede Spalte angewendet werden sollen. Jede Spalte der Tabelle kann einen NULL
-Wert enthalten, der durch die Übergabe eines NULL
-Werts im Array angezeigt wird. Sie brauchen eine Möglichkeit, zwischen einem nicht vorhandenen Array-Schlüssel und einem Array-Wert zu unterscheiden, der auf NULL
gesetzt ist. Das ist der Unterschied zwischen dem Aktualisieren des Spaltenwerts und dem Aktualisieren des Spaltenwerts auf NULL
.
Zweitens funktioniert Zoredaches Antwort , array_key_exists()
korrekt für den 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 praktisch überall zutrifft, kann ich feststellen, dass es zwischen den nicht vorhandenen und den Variablen NULL
keine Mehrdeutigkeit gibt. Ich rufe array_key_exists()
auf, der offiziell einfachste Weg in PHP, um wirklich zu überprüfen das Vorhandensein einer Variablen.
(Ich kann mir nur einen anderen Fall für Klasseneigenschaften vorstellen, für die es property_exists()
gibt, das laut seiner docs ähnlich wie array_key_exists()
dahingehend funktioniert, dass es richtig unterscheidet, nicht gesetzt zu sein und auf NULL
gesetzt zu sein. )
Wenn die Variable, die Sie überprüfen, im globalen Bereich liegt, können Sie Folgendes tun:
array_key_exists('v', $GLOBALS)
Der Versuch, einen Überblick über die verschiedenen Diskussionen und Antworten zu geben:
Es gibt keine einzige Antwort auf die Frage, die alle Verwendungsmöglichkeiten von isset
ersetzen kann. Einige Anwendungsfälle werden von anderen Funktionen behandelt, während andere der Prüfung nicht standhalten oder einen zweifelhaften Wert jenseits des Codes haben Golf. Andere Anwendungsfälle sind nicht "defekt" oder "inkonsistent", sondern zeigen, warum die Reaktion von isset
auf null
das logische Verhalten ist.
Arrays können wie Sammlungen von Variablen behandelt werden, wobei unset
und isset
sie so behandeln, als wären sie. Da sie jedoch iteriert, gezählt usw. werden können, ist ein fehlender Wert nicht mit dem Wert null
identisch.
In diesem Fall lautet die Antwort benutze array_key_exists()
anstelle von isset()
.
Da dies das Array zur Überprüfung als Funktionsargument benötigt, wird PHP immer noch "Notices" auslösen, wenn das Array selbst nicht existiert. In einigen Fällen kann mit Recht argumentiert werden, dass jede Dimension zuerst initialisiert werden sollte, damit der Hinweis seine Aufgabe erfüllt. In anderen Fällen würde eine "rekursive" array_key_exists
-Funktion, die nacheinander jede Dimension des Arrays prüft, dies vermeiden, wäre aber im Grunde dasselbe wie @array_key_exists
. Es ist auch etwas tangential zur Behandlung von null
-Werten.
In der traditionellen Theorie der "objektorientierten Programmierung" sind Verkapselung und Polymorphismus Schlüsseleigenschaften von Objekten; In einer klassenbasierten OOP -Implementierung wie PHP werden die gekapselten Eigenschaften als Teil der Klassendefinition deklariert und erhalten Zugriffsebenen (public
, protected
oder private
).
Mit PHP können Sie einem Objekt jedoch auch dynamisch Eigenschaften hinzufügen, wie Sie es mit Schlüsseln für ein Array tun würden, und einige Leute verwenden klassenlose Objekte (technisch gesehen Instanzen des eingebauten stdClass
, das keine Methoden hat) oder private Funktionalität) in ähnlicher Weise wie assoziative Arrays. Dies führt zu Situationen, in denen eine Funktion möglicherweise wissen möchte, ob dem ihr zugewiesenen Objekt eine bestimmte Eigenschaft hinzugefügt wurde.
Wie bei Array-Schlüsseln ist eine Lösung zum Überprüfen von Objekteigenschaften in der Sprache enthalten, die vernünftigerweise property_exists
heißt.
register_globals
und andere Verschmutzung des globalen NamespacesDas Feature register_globals
fügte dem globalen Bereich Variablen hinzu, deren Namen durch Aspekte der HTTP-Anforderung bestimmt wurden (Parameter GET und POST sowie Cookies). Dies kann zu fehlerhaftem und unsicherem Code führen, weshalb er seit PHP 4.2, veröffentlicht im August 20 standardmäßig deaktiviert und in PHP 5.4, veröffentlicht im März 2012 vollständig entfernt wurde. Es ist jedoch möglich, dass auf einigen Systemen diese Funktion noch aktiviert oder emuliert ist. Es ist auch möglich, den globalen Namespace mit dem Schlüsselwort global
oder dem Array $GLOBALS
auf andere Weise zu "verschmutzen".
Erstens ist es unwahrscheinlich, dass register_globals
selbst unerwartet eine null
-Variable erzeugt, da die Werte für GET, POST und Cookie immer Zeichenfolgen sind (wobei ''
weiterhin true
von isset
zurückgibt) und die Variablen im Sitzungsprogramm vollständig unter Kontrolle sein sollten.
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 Code irgendwo anders zwischen den beiden Zuständen unterscheiden würde. Allein ist diese Möglichkeit ein Argument gegen , ein solches zu machen Unterscheidung.
get_defined_vars
und compact
Einige selten verwendete Funktionen in PHP, wie get_defined_vars
und compact
, ermöglichen es Ihnen, Variablennamen so zu behandeln, als wären sie Schlüssel in einem Array. Für globale Variablen erlaubt das super-globale Array $GLOBALS
einen ähnlichen Zugriff und ist häufiger. Diese Zugriffsmethoden verhalten sich anders, wenn eine Variable nicht im entsprechenden Bereich definiert ist.
Wenn Sie sich entschlossen haben, eine Reihe von Variablen mithilfe eines dieser Mechanismen als Array zu behandeln, können Sie mit ihr dieselben Vorgänge ausführen wie mit einem normalen Array. Folglich siehe 1.
Funktionen, die nur existierten, um vorherzusagen, wie sich diese Funktionen verhalten werden (z. B. "Wird das von get_defined_vars
zurückgegebene Array einen Schlüssel" foo "enthalten?"), Sind überflüssig, da Sie die Funktion einfach ausführen und ohne negative Auswirkungen herausfinden können .
$$foo
)Obwohl dies nicht ganz mit Funktionen identisch ist, die eine Gruppe von Variablen in ein assoziatives Array umwandeln, kann und sollte dies in den meisten Fällen mit "Variablenvariablen" ("einer Variablen zuweisen, die auf der Grundlage dieser anderen Variablen benannt wurde") geschehen wurde geändert, um stattdessen ein assoziatives Array zu verwenden.
Ein Variablenname ist im Grunde die Bezeichnung, die der Programmierer einem Wert gibt. Wenn Sie es zur Laufzeit ermitteln, handelt es sich nicht wirklich um eine Bezeichnung, sondern um einen Schlüssel in einem Schlüsselwertspeicher. Praktischer gesagt, wenn Sie kein Array verwenden, verlieren Sie 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
überschrieben wird.
Sobald der Code für die Verwendung eines assoziativen Arrays geändert wurde, kann er für Lösung 1 verwendet werden. Der indirekte Zugriff auf Objekteigenschaften (z. B. $foo->$property_name
) kann mit Lösung 2 adressiert werden.
isset
ist so viel einfacher zu tippen als array_key_exists
Ich bin mir nicht sicher, ob dies wirklich relevant ist, aber ja, die Funktionsnamen von PHP können manchmal ziemlich langwierig und inkonsistent sein. Anscheinend haben prähistorische Versionen von PHP die Länge eines Funktionsnamens als Hash-Schlüssel verwendet, also hat Rasmus bewusst Funktionsnamen wie htmlspecialchars
erfunden, damit sie eine ungewöhnliche Anzahl von Zeichen haben ...
Zumindest schreiben wir noch kein Java, oder? ;)
Die Handbuchseite zu Variablengrundlagen enthält diese Anweisung:
Nicht initialisierte Variablen haben je nach Kontext, in dem sie verwendet werden, einen Standardwert ihres Typs
Ich bin mir nicht sicher, ob es in der Zend Engine einen Begriff von "nicht initialisiertem, aber bekanntem Typ" gibt oder ob dies zu viel in die Anweisung einliest.
Klar ist, dass es keinen praktischen Unterschied zu ihrem Verhalten gibt, da das auf dieser Seite beschriebene Verhalten für nicht initialisierte Variablen mit dem Verhalten einer Variablen mit dem Wert null
identisch ist. Um ein Beispiel auszuwählen, werden sowohl $a
als auch $b
in diesem Code als Ganzzahl 42
ausgegeben:
unset($a);
$a += 42;
$b = null;
$b += 42;
(Der erste Befehl gibt einen Hinweis auf eine nicht deklarierte Variable aus, um Sie dazu zu bringen, besseren Code zu schreiben. Es spielt jedoch keine Rolle, wie der Code tatsächlich ausgeführt wird.)
(Beibehaltung der letzten, da sie viel länger ist als die anderen. Vielleicht bearbeite ich sie später ...)
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
zurückgeben kann, besteht die Möglichkeit, dass echo
nicht erreicht wird, obwohl some_test
true
zurückgegeben hat. Der Programmierer wollte feststellen, wann $result
noch nie festgelegt wurde, aber PHP lässt dies nicht zu.
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 bestanden wird, sodass nicht festgestellt werden kann, ob nachfolgende Tests bestanden wurden oder nicht. Dies ist tatsächlich ein sehr häufiger Fehler, wenn Variablen nicht richtig initialisiert werden.
Um dies zu beheben, müssen wir etwas in der Zeile tun, in der ich kommentiert habe, dass etwas fehlt. Die naheliegendste Lösung besteht darin, $result
auf einen "Endwert" zu setzen, den some_function
niemals zurückgeben kann. Wenn dies null
ist, funktioniert der Rest des Codes einwandfrei. Wenn es keinen natürlichen Kandidaten für einen Endwert gibt, weil some_function
einen extrem unvorhersehbaren Rückgabetyp hat (was an sich wahrscheinlich ein schlechtes Zeichen ist), dann wird ein zusätzlicher boolescher Wert, z. $found
könnte stattdessen verwendet werden.
very_null
-KonstantePHP könnte theoretisch eine spezielle Konstante - sowie null
- zur Verwendung als Terminalwert bereitstellen. Vermutlich wäre es illegal, dies von einer Funktion zurückzugeben, oder es würde zu null
gezwungen, und das gleiche würde wahrscheinlich für die Weitergabe als Funktionsargument gelten. Das würde diesen speziellen Fall etwas einfacher machen, aber sobald Sie sich entschlossen haben, den Code neu zu faktorisieren - zum Beispiel, um die innere Schleife in eine separate Funktion zu versetzen -, wird er unbrauchbar. Wenn die Konstante zwischen Funktionen übergeben werden könnte, könnten Sie nicht garantieren, dass some_function
sie nicht zurückgibt, sodass sie nicht mehr als universeller Terminalwert verwendet werden kann.
Das Argument für die Erkennung nicht initialisierter Variablen in diesem Fall läuft auf das Argument für diese spezielle Konstante hinaus: Wenn Sie den Kommentar durch unset($result)
ersetzen und diesen anders als $result = null
behandeln, geben Sie einen "Wert" für $result
ein, der nicht weitergegeben werden kann, und kann nur von bestimmten eingebauten Funktionen erkannt werden.
Eine andere Art, darüber nachzudenken, was der letzte if
fragt, ist "Hat irgendetwas eine Zuordnung zu $result
vorgenommen?". Anstatt es als speziellen Wert von $result
zu betrachten, könnten Sie sich dies als "Metadaten" über die Variable vorstellen, ein bisschen wie Perls "Variablen-Tainting". Anstelle von isset
können Sie auch has_been_assigned_to
und statt unset
reset_assignment_state
nennen.
Aber wenn ja, warum bei einem Booleschen anhalten? Was ist, wenn Sie wissen möchten , wie oft der Test bestanden wurde; Sie können Ihre Metadaten einfach auf eine Ganzzahl erweitern und get_assignment_count
und reset_assignment_count
...
Offensichtlich hätte das Hinzufügen eines solchen Features einen Kompromiss zwischen Komplexität und Leistung der Sprache zur Folge, sodass es sorgfältig gegen die erwartete Nützlichkeit abgewogen werden müsste. Wie bei einer very_null
-Konstante wäre sie nur unter sehr engen Umständen nützlich und wäre in ähnlicher Weise resistent gegen Re-Factoring.
Die hoffentlich naheliegende Frage ist, warum die Laufzeit-Engine PHP im Voraus davon ausgehen sollte, dass Sie solche Dinge im Auge behalten möchten, anstatt es Ihnen zu überlassen, dies explizit mit normalem Code zu tun.
Manchmal verliere ich mich beim Versuch, herauszufinden, welche Vergleichsoperation in einer bestimmten Situation verwendet werden soll. isset()
gilt nur für nicht initialisierte oder explizit leere Werte. Das Übergeben/Zuweisen von Null ist eine hervorragende Möglichkeit, um sicherzustellen, dass ein logischer Vergleich wie erwartet funktioniert.
Es ist jedoch etwas schwierig, darüber nachzudenken. Hier ist eine einfache Matrix, die vergleicht, wie unterschiedliche 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 Etiketten ein wenig komprimiert:
$a;
verweist auf eine deklarierte, aber nicht zugewiesene Variable$a = null;
$a = [];
$a = 0;
$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 durchführen, überprüfen Sie diese Übersicht:
https://Gist.github.com/mfdj/8165967
Sie können das kompakte Sprachkonstrukt verwenden, um das Vorhandensein einer Nullvariablen zu testen. Nicht vorhandene Variablen 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.
}
Für Variablen im globalen Bereich können Sie natürlich auch array_key_exists () verwenden.
B.t.w. Ich persönlich würde Situationen wie die Pest vermeiden, in denen es einen semantischen Unterschied zwischen einer nicht vorhandenen Variablen und der Variablen mit einem Nullwert gibt. PHP und die meisten anderen Sprachen glauben einfach nicht, dass es gibt.
Ich denke, die offensichtliche Antwort auf all das ist ....__: Initialisieren Sie Ihre Variablen nicht als NULL, sondern als etwas, das relevant ist für das, was sie werden sollen.
NULL sollte als "nicht vorhandener Wert" behandelt werden. Dies ist die Bedeutung von NULL . Die Variable kann nicht als für PHP vorhanden klassifiziert werden, da nicht bekannt ist, um welche Art von Entität es sich handelt versuchen zu sein. Es kann auch nicht existieren, daher sagt PHP einfach "Gut, das ist nicht der Fall, weil es sowieso keinen Sinn hat und NULL ist meine Art, dies zu sagen".
Lasst uns jetzt streiten. "Aber NULL ist wie 0 oder False oder ''.
Falsch, 0-FALSE- '' werden immer noch als leere Werte klassifiziert, aber sie werden als eine Art Wert oder eine vorbestimmte Antwort auf eine Frage angegeben.FALSEist die Antwort auf Ja oder Nein, '' ist die Antwort auf den Titel, den jemand eingereicht hat, und 0 ist die Antwort auf Menge oder Zeit usw. Sie sind als einige festgelegt Art der Antwort/des Ergebnisses, wodurch sie als gesetzt gelten.
NULL ist einfach keine Antwort, es sagt uns nicht Ja oder Nein und es sagt uns nicht die Zeit und es sagt uns nicht, dass ein leerer String übergeben wurde. Das ist die grundlegende Logik, um NULL zu verstehen.
Es geht nicht darum, verrückte Funktionen zu schaffen, um das Problem zu umgehen, es ändert lediglich die Art und Weise, wie Ihr Gehirn NULL betrachtet. Wenn es NULL ist, wird davon ausgegangen, dass es nicht als etwas festgelegt ist. Wenn Sie Variablen vordefinieren, definieren Sie sie als 0, FALSE oder "" abhängig von der Art der Verwendung, die Sie für sie beabsichtigen.
Fühlen Sie sich frei, dies zu zitieren .. __ es ist aus meinem logischen Kopf :)
Objekteigenschaften können durch property_exists auf Existenz geprüft werden.
Beispiel aus einem Unit-Test:
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 zu die Diskussion von greatbigmassive darüber, was NULL bedeutet betrachten Sie, was "die Existenz einer Variablen" tatsächlich bedeutet.
In vielen Sprachen müssen Sie jede Variable explizit deklarieren, bevor Sie sie verwenden ; Dies kann den Typ bestimmen, aber was noch wichtiger ist, es deklariert den Gültigkeitsbereich . Eine Variable "existiert" überall in ihrem Bereich und nirgendwo außerhalb - sei es eine ganze Funktion oder ein einzelner "Block".
Innerhalb seines Gültigkeitsbereichs weist eine Variable einem Label , das Sie als Programmierer ausgewählt haben, eine Bedeutung zu. Außerhalb des Gültigkeitsbereichs ist dieses Label bedeutungslos (es ist grundsätzlich unerheblich, ob Sie dasselbe Label in einem anderen Gültigkeitsbereich verwenden).
In PHP müssen Variablen nicht deklariert werden - sie werden zum Leben erweckt, sobald Sie sie benötigen. Wenn Sie zum ersten Mal in eine Variable schreiben, weist PHP dieser Variablen einen Eintrag im Speicher zu. Wenn Sie aus einer Variablen lesen, für die derzeit kein Eintrag vorhanden ist, geht PHP davon aus, dass diese Variable den Wert NULL
hat.
Automatische Codequalitätserkenner warnen Sie jedoch im Allgemeinen, wenn Sie eine Variable verwenden, ohne sie zuerst zu "initialisieren". Erstens hilft dies bei der Erkennung von Tippfehlern, z. B. beim Zuweisen zu $thingId
, aber beim Lesen aus $thing_id
; zweitens zwingt es Sie, den Gültigkeitsbereich, über den diese Variable eine Bedeutung hat, genau wie eine Deklaration zu betrachten.
Jeder Code, der sich darum kümmert, ob eine Variable "existiert", gehört zum Gültigkeitsbereich dieser Variablen - unabhängig davon, ob sie initialisiert wurde oder nicht, haben Sie als Programmierer gegeben, dass die Bezeichnung an dieser Stelle des Codes bedeutet. 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 Funktionsweise von PHP ist es möglich, Code zu schreiben, der den Namespace vorhandener Variablen nicht als Bereich von Bezeichnungen behandelt, denen Sie eine Bedeutung gegeben haben, sondern als eine Art Schlüsselwertspeicher. Sie können beispielsweise folgenden Code ausführen: $var = $_GET['var_name']; $$var = $_GET['var_value'];
. Nur weil du kannst, heißt das nicht, dass es eine gute Idee ist.
Es stellt sich heraus, dass PHP Schlüsselwertspeicher, sogenannte assoziative Arrays, viel besser darstellen kann. Obwohl die Werte eines Arrays wie Variablen behandelt werden können, können Sie auch Operationen für das gesamte Array ausführen. Wenn Sie ein assoziatives Array haben, können Sie mit 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. Natürlich , wenn Sie eine Klasse definieren, können Sie deklarieren, welche Eigenschaften sie hat - Sie können sogar wählen zwischen public
, private
und protected
Gültigkeitsbereich.
Obwohl es einen technischen Unterschied zwischen einer Variablen (im Gegensatz zu einem Array-Schlüssel oder einer Objekteigenschaft) gibt, die nicht initialisiert wurde (oder die explizit unset()
war) und einer Deren Wert ist null
. Jeder Code, der diesen Unterschied als bedeutungsvoll ansieht , verwendet Variablen so, wie 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 fällt (meiner Meinung nach) nicht in den Bereich dieser Funktion. Es gibt keine anständige Problemumgehung, um zu bestimmen, ob eine Variable NULL ist, weil sie nicht oder explizit auf NULL gesetzt 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()
zu prüfen:
$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 werde dazu noch zwei Cent hinzufügen. Ein Grund, warum dieses Problem verwirrend ist, liegt darin, dass dieses Szenario dasselbe Ergebnis zu liefern scheint, wenn der Fehlerbericht nicht voll ausgegeben wird:
$a = null;
var_dump($a); // NULL
var_dump($b); // NULL
Sie können aus diesem Ergebnis annehmen, dass der Unterschied zwischen $a = null
und $b
überhaupt nicht definiert ist.
Kurbelfehlerberichterstattung:
NULL
Notice: Undefined variable: b in xxx on line n
NULL
Hinweis: hat einen undefinierten Variablenfehler ausgelöst, der Ausgabewert von var_dump
ist jedoch noch NULL
.
PHP hat offensichtlich eine interne Fähigkeit, zwischen einer Nullvariablen und einer undefinierten Variablen zu unterscheiden. Es scheint mir, dass es eine eingebaute Funktion geben sollte, um dies zu überprüfen.
Ich glaube, die akzeptierte Antwort ist zum größten Teil gut, aber wenn ich sie implementieren würde, würde ich einen Wrapper dafür schreiben. Wie bereits erwähnt in dieser Antwort , muss ich zustimmen, dass ich noch nie eine Situation erlebt habe, in der dies ein Problem war. Ich scheine fast immer in einem Szenario zu enden, in dem meine Variablen entweder gesetzt und definiert sind oder nicht (undefiniert, nicht festgelegt, null, leer usw.). Nicht um zu sagen, dass eine Situation wie diese in der Zukunft nicht auftreten wird, aber da es sich um ein ziemlich einzigartiges Problem zu handeln scheint, bin ich nicht überrascht, dass die PHP -Entwickler sich nicht darum gekümmert haben.
Ich stimme nicht mit deinen Überlegungen zu NULL überein , und zu sagen, dass du deine Einstellung zu NULL ändern musst, ist seltsam.
Ich denke, isset () wurde nicht richtig entworfen, isset () sollte Ihnen sagen, ob die Variable gesetzt wurde und es sollte sich nicht um den tatsächlichen Wert der Variablen handeln.
Wenn Sie die von einer Datenbank zurückgegebenen Werte überprüfen und eine der Spalten einen NULL-Wert hat, möchten Sie trotzdem wissen, ob sie vorhanden ist, auch wenn der Wert NULL ist ... nope vertraut isset () hier nicht.
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 gestaltet sein, dass es so funktioniert:
if(isset($var) && $var===NULL){....
auf diese Weise überlassen wir es dem Programmierer, die Typen zu überprüfen, und isset () nicht zu überlassen, dass es nicht vorhanden ist, da der Wert NULL ist - das ist nur dummes Design
Wenn ich folgendes mache:
echo '<?php echo $foo; ?>' | php
Ich bekomme einen Fehler:
PHP Notice: Undefined variable: foo in /home/altern8/- on line 1
Wenn ich folgendes mache:
echo '<?php if ( isset($foo) ) { echo $foo; } ?>' | php
Ich bekomme den Fehler nicht.
Wenn ich eine Variable habe, die gesetzt werden sollte, mache ich normalerweise etwas wie das Folgende.
$foo = isset($foo) ? $foo : null;
oder
if ( ! isset($foo) ) $foo = null;
Auf diese Weise kann ich später im Skript $ foo sicher verwenden und wissen, dass es "gesetzt" ist und der Standardwert null ist. Später kann ich if ( is_null($foo) ) { /* ... */ }
, wenn ich muss und sicher bin, dass die Variable existiert, auch wenn sie null ist.
Die vollständige isset-Dokumentation liest etwas mehr als das, was ursprünglich eingefügt wurde. Ja, es gibt für eine zuvor festgelegte Variable den Wert "false" zurück, aber es wird auch "Falsch" zurückgegeben, wenn noch keine Variable festgelegt wurde (je), und für alle Variablen, die als unset markiert wurden. Es stellt außerdem fest, dass das NULL-Byte ("\ 0") nicht als Null betrachtet wird und "true" zurückgibt.
Bestimmen Sie, ob eine Variable festgelegt ist.
Wenn eine Variable mit .__ gelöscht wurde. unset () wird nicht mehr gesetzt . isset () gibt FALSE zurück, wenn ein .__ getestet wird. Variable, die auf NULL gesetzt wurde . Beachten Sie auch, dass ein NULL-Byte ("\ 0") .__ ist. ist nicht gleichbedeutend mit PHP NULL Konstante.
Versuchen Sie es mit
unset($v)
Es scheint, dass die einzige Zeit, zu der eine Variable nicht gesetzt wird, darin besteht, dass sie speziell nicht gesetzt ist ($ v). Es scheint, als ob Ihre Bedeutung von 'Existenz' anders ist als die Definition von PHP. NULL ist sicherlich vorhanden, es ist NULL.
In all meinen Jahren der PHP - Programmierung muss ich sagen, dass es noch nie ein Problem gab, wenn isset()
für eine null-Variable false zurückgibt. OTOH, ich habe Probleme mit isset()
bei einem Null-Array-Eintrag festgestellt - aber array_key_exists()
funktioniert in diesem Fall korrekt.
Für einige Vergleiche definiert Icon eine nicht verwendete Variable explizit als Rückgabe von &null
, sodass Sie den Test is-null in Icon verwenden, um auch nach einer nicht gesetzten Variablen zu suchen. Das macht die Sache einfacher. Auf der anderen Seite verfügt Visual BASIC über mehrere Status für eine Variable, die keinen Wert hat (Null, Leer, Nothing, ...), und Sie müssen häufig nach mehr als einem dieser Werte suchen. Dies ist bekanntermaßen eine Fehlerquelle.
Ich denke, die einzige vollständige Lösung besteht darin, Mitteilungen mit zu melden
error_reporting(E_ALL); // Enables E_NOTICE
Sie müssen jedoch alle Hinweise korrigieren, die unter anderem von undefinierten Variablen, Konstanten, Array-Schlüsseln und Klasseneigenschaften generiert werden. Sobald Sie dies getan haben, müssen Sie sich nicht um den Unterschied zwischen null und nicht deklarierten Variablen kümmern, und die Mehrdeutigkeit verschwindet.
Das Aktivieren von notice reporting ist möglicherweise nicht in allen Situationen eine gute Alternative, aber es gibt gute Gründe, es zu aktivieren:
Warum sollte ich E_NOTICE-Fehler beheben?
In meinem Fall arbeitete ich mehr als ein Jahr in einem Projekt ohne es, wurde aber verwendet, um Variablen zu deklarieren, daher war der Übergang schnell.
Der einzige Weg, um festzustellen, ob eine Variable im aktuellen Bereich definiert ist ($GLOBALS
ist nicht vertrauenswürdig), ist array_key_exists( 'var_name', get_defined_vars() )
.
Gemäß dem PHP - Handbuch für die Funktion empty () "Bestimmen Sie, ob eine Variable als leer betrachtet wird. Eine Variable wird als leer betrachtet, wenn sie nicht vorhanden ist oder wenn ihr Wert gleich FALSE ist. Empty () generiert nicht eine Warnung, wenn die Variable nicht vorhanden ist. " (Meine Betonung.) Das heißt, die leere () - Funktion sollte laut Titel Question die beste Methode sein, um das Vorhandensein einer Variablen in PHP zu testen.
Dies ist jedoch nicht gut genug, da die empty () - Funktion von einer Variablen getäuscht werden kann, die existiert und auf NULL gesetzt ist.
Ich unterbreche meine frühere Antwort, um etwas Besseres zu präsentieren, weil sie weniger umständlich ist als meine ursprüngliche Antwort (die auf diese Unterbrechung folgt, um zu vergleichen).
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
}
Mit der obigen Funktion können zwei einfache Codezeilen erkennen, ob eine Variable undefiniert ist:
ob_start(); //pass all output messages (including errors) to a buffer
if(undef($testvar===null)) //in this case the variable being tested is $testvar
Sie können diese beiden Zeilen mit allem geeigneten folgen, wie in diesem Beispiel:
echo("variable is undefined");
else
echo("variable exists, holding some value");
Ich wollte den Aufruf von ob_start () und ($ testvar === null) in die Funktion einfügen und die Variable einfach an die Funktion übergeben, aber es funktioniert nicht. Selbst wenn Sie versuchen, "Referenzübergabe" der Variablen für die Funktion zu verwenden, wurde die Variable BECOMES definiert, und die Funktion kann niemals feststellen, dass sie zuvor undefiniert war. Was hier präsentiert wird, ist ein Kompromiss zwischen dem, was ich tun wollte, und dem, was tatsächlich funktioniert.
Das Vorangegangene impliziert, dass es eine andere Möglichkeit gibt, immer die Fehlermeldung "Undefined variable" zu vermeiden. (Die Annahme hier ist, dass eine solche Meldung verhindert werden soll, warum Sie testen möchten, ob eine Variable nicht definiert ist.)
function inst(&$v) { return; } //receive any variable passed by reference; instantiates the undefined
Rufen Sie einfach diese Funktion auf, bevor Sie etwas mit Ihrer $ testvar machen:
inst($testvar); //The function doesn't affect any value of any already-existing variable
Der Wert der neu instanziierten Variablen ist natürlich auf Null gesetzt!
(Unterbrechung endet)
Nach einigem Lernen und Experimentieren funktioniert also garantiert etwas:
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
}
Die Erklärung: Eine Variable $ er wird mit dem Standardwert "Kein Fehler" initialisiert. Eine "Handlerfunktion" ist definiert. Wenn $ testvar (die Variable, die wir wissen möchten, ob undefiniert ist oder nicht) den vorläufigen empty () -Funktionstest besteht, führen wir den gründlicheren Test durch. Wir rufen die Funktion set_error_handler () auf, um die zuvor definierte Handlerfunktion zu verwenden. Dann führen wir einen einfachen Identitätsvergleich mit $ testvar durch, dessen Fehler, wenn er nicht definiert wird, einen Fehler auslöst. Die Handlerfunktion erfasst den Fehler und prüft insbesondere, ob der Fehler darauf zurückzuführen ist, dass die Variable undefiniert ist. Das Ergebnis wird in die Fehlerinformationsvariable $ er gestellt, die wir später testen können, um zu tun, was wir wollen, weil wir sicher sind, ob $ testvar definiert wurde oder nicht. Da wir die Handler-Funktion nur für diesen begrenzten Zweck benötigen, stellen wir die ursprüngliche Fehlerbehandlungsfunktion wieder her. Die Funktion "myHndlr" muss nur einmal deklariert werden. Der andere Code kann an beliebige Stellen kopiert werden, für $ testvar oder jede andere Variable, die wir auf diese Weise testen möchten.