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

187

Aus den isset()Dokumenten :

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

isset()Überprüft grundsätzlich nicht, ob die Variable überhaupt gesetzt ist, sondern ob sie auf etwas anderes als gesetzt ist NULL.

Was ist angesichts dessen der beste Weg, um tatsächlich zu prüfen, ob eine Variable vorhanden ist? Ich habe so etwas versucht wie:

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

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

@($v === NULL)

funktioniert genau so @is_null($v), also ist das auch raus.

Wie sollen wir zuverlässig prüfen, ob in PHP eine Variable vorhanden ist?


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

<?php
$a = array('b' => NULL);
var_dump($a);

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

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

Sie können die Mehrdeutigkeit sehen, über die ich mit der isset()Funktion spreche . Hier ist die Ausgabe aller drei var_dump()s:

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

Weiter bearbeiten: zwei Dinge.

Erstens ein Anwendungsfall. Ein Array wird in die Daten einer SQL- UPDATEAnweisung umgewandelt, wobei die Schlüssel des Arrays die Spalten der Tabelle und die Werte des Arrays die Werte sind, die auf jede Spalte angewendet werden sollen. Jede Spalte der Tabelle kann einen NULLWert enthalten, der durch Übergabe eines NULLWerts im Array gekennzeichnet ist. Sie benötigen eine Möglichkeit, zwischen einem nicht vorhandenen Array-Schlüssel und dem Wert eines Arrays zu unterscheidenNULL . Das ist der Unterschied zwischen dem Nicht-Aktualisieren des Spaltenwerts und dem Aktualisieren des Spaltenwerts auf NULL.

Zweitens Zoredache Antwort , array_key_exists()funktioniert einwandfrei , für meinen oben 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 das richtig fast überall Griffe kann ich dort sehen ist , jede Zweideutigkeit zwischen Variablen , die nicht existieren und Variablen, die gesetzt sind NULL, bin ich rufe array_key_exists()den offiziellen einfachste Weg , in PHP wirklich für die Existenz einer Variablen zu überprüfen .

(Nur ein anderer Fall, den ich mir vorstellen kann , betrifft Klasseneigenschaften, für die es gibt property_exists(), die laut ihren Dokumenten ähnlich funktionieren, array_key_exists()indem sie richtig zwischen Nicht-Setzen und Setzen auf unterscheiden NULL.)

Chazomaticus
quelle
Sie können nicht überprüfen - aber warum müssen Sie?
zu viel PHP
12
NULL hat in PHP eine ganz bestimmte Bedeutung und ist ein völlig anderes Konzept als die, ob eine Variable gesetzt ist oder nicht.
Chazomaticus
33
Es gibt Gründe, zwischen null und nicht vorhanden zu unterscheiden. Sie erstellen beispielsweise ein Objekt, um eine Zeile in einer Datenbanktabelle darzustellen. Für jede Spalte in der Zeile erstellen Sie eine private Variable, auf die nur über die Getter-Methode des Objekts zugegriffen werden kann. Angenommen, ein Spaltenwert ist null. Woher weiß diese Getter-Methode, ob die Tabelle keine solche Spalte enthält oder ob dieses Objekt dort nur einen Nullwert hat? Glücklicherweise ist in meinem Fall die private Variable tatsächlich ein Eintrag in einem privaten Array, sodass ich array_key_exists verwenden kann, aber dies ist ein echtes Problem.
Nathan Long
1
Es wurde aus neuen Versionen von PHP entfernt, ja. Leider ist es nicht bei jeder Bereitstellung von PHP verschwunden. Außerdem scheint es ein sinnloses semantisches Detail zu sein, darüber zu streiten, ob es sich um Array-Elemente oder -Variablen handelt. Unabhängig davon, welche Standards Code Ihrer Meinung nach einhalten sollte, ist es hilfreich zu wissen, wie man eine Inkonsistenz in der PHP-Sprache umgeht.
Chazomaticus
2
@chazomaticus Aber Variablen und Array-Elemente sind grundlegend verschiedene Dinge ; Nur weil Sie einige der gleichen Dinge mit ihnen machen können, heißt das nicht, dass sie zu 100% austauschbar sind oder sein sollten. Hier gibt es keine "Inkonsistenz in der PHP-Sprache", nur etwas, das Sie nicht mögen / verstehen. Was register_globals, bin ich kämpfen nach wie vor einer Situation zu denken , wo , dass auch eine solche Unterscheidung erfordern würde, da alles von der HTTP - Anforderung registriert immer ein String sein würde, nicht null.
IMSoP

Antworten:

97

Wenn sich die zu überprüfende Variable im globalen Bereich befindet, können Sie Folgendes tun:

array_key_exists('v', $GLOBALS) 
Zoredache
quelle
3
Ah ha! JETZT redest du! Wie würden Sie das beispielsweise für Klasseneigenschaften tun?
Chazomaticus
22
Als Variation kann on, wenn die Prüfung auch für lokale Bereichsvariablen funktionieren muss, a ausführen $defined_vars = get_defined_vars();und dann über testen array_key_exists('v', $defined_vars);.
Henrik Opel
1
Das sieht für mich ein bisschen hässlich aus, aber für den Fall, dass Sie tatsächlich ein Array-Element überprüfen, ist es viel sinnvoller: isset($foo[$bar])wirdarray_key_exists($bar, $foo)
Arild
property_existsscheint vielversprechend, außer dies:> Die Funktion property_exists () kann keine Eigenschaften erkennen, auf die mit der magischen Methode __get magisch zugegriffen werden kann.
Alexw
@alexw Variablen, die über __get "erstellt" wurden, existieren tatsächlich nicht. __get ist ein beliebiger Code, der als Ersatz für nicht vorhandene Variablen verwendet wird und unabhängig davon, ob relevante Daten jemals gespeichert wurden, alles zurückgeben kann, was er möchte.
Brilliand
46

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

Es gibt keine einzige Antwort auf die Frage, die alle Verwendungsmöglichkeiten ersetzen issetkann. Einige Anwendungsfälle werden von anderen Funktionen behandelt, während andere der Prüfung nicht standhalten oder über Code-Golf hinaus einen zweifelhaften Wert haben. Weit davon entfernt, "kaputt" oder "inkonsistent" zu sein, zeigen andere Anwendungsfälle, warum issetdie Reaktion auf nulldas logische Verhalten ist.

Echte Anwendungsfälle (mit Lösungen)

1. Array-Schlüssel

Arrays können wie Sammlungen von Variablen behandelt werden, mit unsetund issetbehandelt sie , als ob sie waren. Da sie jedoch iteriert, gezählt usw. werden können, ist ein fehlender Wert nicht mit einem Wert identisch, dessen Wert ist null.

Die Antwort in diesem Fall ist zu verwenden , array_key_exists()stattisset() .

Da das Array als Funktionsargument überprüft werden muss, gibt PHP weiterhin "Benachrichtigungen" aus, wenn das Array selbst nicht vorhanden ist. In einigen Fällen kann mit Recht argumentiert werden, dass jede Dimension zuerst initialisiert werden sollte, damit die Benachrichtigung ihre Aufgabe erfüllt. In anderen Fällen würde eine "rekursive" array_key_existsFunktion, die nacheinander jede Dimension des Arrays prüft, dies vermeiden, wäre aber im Grunde dieselbe wie @array_key_exists. Es ist auch etwas tangential zum Umgang mitnull Werten.

2. Objekteigenschaften

In der traditionellen Theorie der "objektorientierten Programmierung" sind Kapselung und Polymorphismus Schlüsseleigenschaften von Objekten; in einer klassenbasierten OOP Implementierung wie PHP, werden die eingekapselten Eigenschaften als Teil der Klassendefinition deklarieren, und gegebenen Zugriffsebene ( public, protectedoderprivate ).

Mit PHP können Sie einem Objekt jedoch auch dynamisch Eigenschaften hinzufügen, wie Sie es für ein Array tun würden, und einige Benutzer verwenden klassenlose Objekte (technisch gesehen Instanzen des integrierten Objekts) stdClass , das keine Methoden oder privaten Funktionen enthält) in ähnlicher Weise Weg zu assoziativen 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 in der Sprache eine Lösung zum Überprüfen von Objekteigenschaften enthalten, die vernünftigerweise aufgerufen wirdproperty_exists .

Nicht vertretbare Anwendungsfälle mit Diskussion

3. register_globalsund andere Verschmutzung des globalen Namespace

Die register_globalsFunktion fügte dem globalen Bereich Variablen hinzu, deren Namen durch Aspekte der HTTP-Anforderung (GET- und POST-Parameter sowie Cookies) bestimmt wurden. Dies kann zu fehlerhaftem und unsicherem Code führen, weshalb er seit PHP 4.2, veröffentlicht im August 2000, standardmäßig deaktiviert und in PHP 5.4, veröffentlicht im März 2012, vollständig entfernt wurde . Es ist jedoch möglich, dass einige Systeme noch mit aktivierter oder emulierter Funktion ausgeführt werden. Es ist auch möglich, den globalen Namespace mit dem globalSchlüsselwort oder $GLOBALSArray auf andere Weise zu "verschmutzen" .

Erstens register_globalsist es unwahrscheinlich , dass selbst unerwartet eine nullVariable erzeugt wird, da die GET-, POST- und Cookie-Werte immer Zeichenfolgen sind (wobei ''immer noch truevon zurückgegeben wird isset) und die Variablen in der Sitzung vollständig unter der Kontrolle des Programmierers stehen sollten.

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

4. get_defined_varsundcompact

Mit einigen in PHP selten verwendeten Funktionen wie get_defined_varsund compactkönnen Sie Variablennamen so behandeln, als wären sie Schlüssel in einem Array. Für globale Variablen ermöglicht das superglobale Array$GLOBALS einen ähnlichen Zugriff und ist häufiger. Diese Zugriffsmethoden verhalten sich anders, wenn eine Variable nicht im entsprechenden Bereich definiert ist.

Sobald Sie sich entschieden haben, eine Reihe von Variablen mithilfe eines dieser Mechanismen als Array zu behandeln, können Sie dieselben Operationen wie bei jedem normalen Array ausführen. Folglich siehe 1.

Funktionen, die nur existierten, um vorherzusagen, wie sich diese Funktionen verhalten werden (z. B. "Gibt es einen Schlüssel 'foo' in dem von zurückgegebenen Array get_defined_vars?") , Sind überflüssig, da Sie die Funktion einfach ausführen und ohne negative Auswirkungen herausfinden können.

4a. Variable Variablen ( $$foo)

Obwohl dies nicht ganz mit Funktionen identisch ist, die eine Reihe von Variablen in ein assoziatives Array verwandeln, kann und sollte in den meisten Fällen die Verwendung von "Variablenvariablen" ("Zuweisen einer Variablen, die auf der Grundlage dieser anderen Variablen benannt ist") geändert werden, um stattdessen ein assoziatives Array zu verwenden .

Ein Variablenname ist im Grunde die Bezeichnung, die ein Wert vom Programmierer erhält. Wenn Sie es zur Laufzeit bestimmen, ist es nicht wirklich ein Label, sondern ein 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 überschrieben wird $$foo.

Nach der Änderung zur Verwendung eines assoziativen Arrays kann der Code für Lösung 1 verwendet werden. Der indirekte Zugriff auf Objekteigenschaften (z. B. $foo->$property_name) kann mit Lösung 2 behandelt werden.

5. issetist so viel einfacher zu tippen alsarray_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-Taste verwendet, daher hat Rasmus absichtlich Funktionsnamen so erfunden, htmlspecialcharsdass sie eine ungewöhnliche Anzahl von Zeichen haben würden ...

Zumindest schreiben wir kein Java, oder? ;)

6. Nicht initialisierte Variablen haben einen Typ

Die Handbuchseite zu Variablengrundlagen enthält folgende Anweisung:

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

Ich bin mir nicht sicher, ob es in der Zend Engine eine Vorstellung von "nicht initialisiertem, aber bekanntem Typ" gibt oder ob dies zu viel in die Aussage einliest.

Klar ist, dass es keinen praktischen Unterschied zu ihrem Verhalten macht, da die auf dieser Seite beschriebenen Verhaltensweisen für nicht initialisierte Variablen mit dem Verhalten einer Variablen identisch sind, deren Wert ist null. Um ein Beispiel auszuwählen, werden beide $aund $bin diesem Code als Ganzzahl angezeigt 42:

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

$b = null;
$b += 42;

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

99. Erkennen, ob eine Funktion ausgeführt wurde

(Behalte dieses letzte, 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 zurückkehren some_functionkann null, besteht die Möglichkeit, dass das echonicht erreicht wird, obwohl es some_testzurückgegeben wird true. Der Programmierer wollte erkennen, wann $resultnoch nie eingestellt wurde, aber PHP erlaubt es ihnen 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 $resultes nie explizit initialisiert wird, nimmt es beim Bestehen des ersten Tests einen Wert an, sodass nicht festgestellt werden kann, ob nachfolgende Tests bestanden wurden oder nicht. Dies ist tatsächlich ein äußerst 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, einen "Endwert" some_functionfestzulegen, der niemals zurückkehren kann. wenn das istnull der Fall ist, funktioniert der Rest des Codes einwandfrei. Wenn es keinen natürlichen Kandidaten für einen Endwert gibt, weil er some_functioneinen extrem unvorhersehbaren Rückgabetyp hat (was an sich wahrscheinlich ein schlechtes Vorzeichen ist) $found, könnte stattdessen ein zusätzlicher boolescher Wert verwendet werden, z .

Gedankenexperiment eins: das very_null Konstante

PHP könnte theoretisch eine spezielle Konstante - sowie null- zur Verwendung als Endwert hier bereitstellen ; vermutlich wäre es illegal, dies von einer Funktion zurückzugeben, oder es würde dazu gezwungen werdennull , und dasselbe würde wahrscheinlich für die Übergabe als Funktionsargument gelten. Das würde diesen sehr spezifischen Fall etwas einfacher machen, aber sobald Sie sich entschieden haben, den Code neu zu faktorisieren - zum Beispiel um die innere Schleife in eine separate Funktion zu setzen - würde er unbrauchbar werden. Wenn die Konstante zwischen Funktionen übergeben werden könnte, könnten Sie nicht garantieren, dass some_functionsie nicht zurückgegeben wird, sodass sie als universeller Terminalwert nicht mehr nützlich wäre.

Das Argument zum Erkennen nicht initialisierter Variablen in diesem Fall läuft auf das Argument für diese spezielle Konstante hinaus: Wenn Sie den Kommentar durch einen anderen ersetzen unset($result)und diesen anders behandeln $result = null, führen Sie einen "Wert" für ein$result , der nicht weitergegeben werden kann und nur sein kann von bestimmten eingebauten Funktionen erkannt.

Gedankenexperiment zwei: Zuweisungszähler

Eine andere Art, darüber nachzudenken, was der Letzte iffragt, ist: "Hat irgendetwas eine Aufgabe gemacht $result?" Anstatt es als einen besonderen Wert von zu betrachten $result, könnten Sie sich dies vielleicht als "Metadaten" über die Variable vorstellen, ähnlich wie Perls "Variable Tainting". Also anstatt issetSie es nennen könnte has_been_assigned_to, und nicht unset, reset_assignment_state.

Aber wenn ja, warum bei einem Booleschen aufhören? Was ist, wenn Sie wissen möchten, wie oft der Test bestanden wurde ? Sie können Ihre Metadaten einfach auf eine Ganzzahl erweitern und haben get_assignment_countundreset_assignment_count ...

Offensichtlich würde das Hinzufügen eines solchen Merkmals einen Kompromiss in Bezug auf Komplexität und Leistung der Sprache haben, so dass es sorgfältig gegen seinen erwarteten Nutzen abgewogen werden müsste. Wie bei einer very_nullKonstante wäre sie nur unter sehr engen Umständen nützlich und wäre ähnlich widerstandsfähig gegen Re-Factoring.

Die hoffentlich offensichtliche Frage ist, warum die PHP-Laufzeit-Engine im Voraus davon ausgehen sollte, dass Sie solche Dinge im Auge behalten möchten, anstatt sie explizit mit normalem Code ausführen zu lassen.

IMSoP
quelle
In Bezug auf Klassen und Eigenschaften funktioniert property_exists () leider nicht, wenn die Eigenschaft ein Array ist, zum Beispiel: Klasse {public $ property = array ()}. Wirft einen Fehler.
Andrew
1
@ Andrew Scheint für mich gut zu funktionieren: 3v4l.org/TnAY5 Möchten Sie ein vollständiges Beispiel liefern?
IMSoP
Ja, es scheint gut zu funktionieren. Bei meinem Setup stimmte etwas nicht. Entschuldigung für den Fehlalarm :)
Andrew
20

Manchmal verliere ich mich ein wenig, um 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, um sicherzustellen, dass ein logischer Vergleich wie erwartet funktioniert.

Trotzdem ist es ein wenig schwierig, darüber nachzudenken. Hier ist eine einfache Matrix, in der verglichen wird, wie unterschiedliche Werte durch unterschiedliche Operationen bewertet 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 auf den Tisch zu passen, habe ich die Etiketten 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, truewerden gedruckt undfalse weggelassen.

Sie können die Tests selbst ausführen. Überprüfen Sie diese Liste:
https://gist.github.com/mfdj/8165967

Mark Fox
quelle
Vielleicht aus dem Rahmen dieser Frage heraus, aber Sie möchten vielleicht "0"zur Vollständigkeit und Klarheit der emptyOperation zur Tabelle hinzufügen
Rik Schaaf
17

Sie können das kompakte Sprachkonstrukt verwenden, um die Existenz 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 Fall 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 Bereich auch array_key_exists () verwenden.

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

Matijs
quelle
3
PHP nicht, aber ich würde nicht sagen, dass die meisten anderen Sprachen dies nicht tun. Die meisten Sprachen, die Variablen deklarieren, geben einen Fehler aus, wenn eine Variable nicht deklariert wurde. Sie können sie jedoch auf festlegen NULL. Semantisch NULLsollte "keine Ressource" bedeuten, aber das Nichtdefinieren einer Variablen ist ein Programmiererfehler.
M Miller
1
@MMiller Sicher, aber das Schreiben von Code, der im Fall von "keine Ressource" einem Pfad und im Fall von "Programmiererfehler" einem anderen Pfad folgt, ist ziemlich unsinnig. Wenn Sie nicht deklarierte Variablen während des Debuggens erkennen möchten, verwenden Sie ein statisches Analysetool, um potenzielle Fehler in einer beliebigen Sprache zu finden.
IMSoP
@MMiller, Cool, wie hast du das überhaupt gedacht?
Pacerier
1
@MMiller Dies funktioniert jedoch nicht als Gegenargument, da sich die Anweisung in der Antwort explizit auf "eine nicht vorhandene Variable" bezieht und Ihr Gegenbeispiel auf eine Objekteigenschaft / einen nicht vorhandenen Hash-Schlüssel . Die Unterscheidung zwischen diesen Fällen ist nicht nur zufällig.
IMSoP
1
@MMiller - in der Tat ist das ein besseres Beispiel. Nach mehr als 20 Jahren Programmieren in strengen Sprachen sind die Situationen, in denen ich eine Unterscheidung zwischen undefinedund nullso selten brauchte, dass ich sie nicht vermisse. IMHO ist die Hauptverwendung für undefined"Programmiererfehler in einer nicht strengen Sprache". Wenn ich in einer strengen Sprache einen bestimmten Zustand für benötige client did not state a value, erkläre ich einen der Situation entsprechenden Wert und teste ihn. Im schlimmsten Fall muss eine separate Flag-Variable hinzugefügt werden. Aber das selten zu tun ist besser, als IMMER mit ZWEI verschiedenen Nicht-Wert-Zuständen fertig zu werden !!
ToolmakerSteve
15

NULL erklären, logisch denken

Ich denke, die offensichtliche Antwort auf all dies ist ... Initialisieren Sie Ihre Variablen nicht als NULL, sondern als etwas, das für das relevant ist, 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 mitgeteilt wurde, um welche Art von Entität es sich handelt. Es kann auch nicht existieren, also sagt PHP nur "Gut, es tut es nicht, weil es sowieso keinen Sinn hat und NULL ist meine Art, dies zu sagen".

Ein Argument

Lassen Sie uns jetzt streiten. "Aber NULL ist wie 0 oder FALSE oder '' zu sagen.

Falsch, 0-FALSE- '' werden immer noch als leere Werte klassifiziert, aber sie werden als Werttyp oder vorgegebene Antwort auf eine Frage angegeben. FALSE ist 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 werden als eine Art von Antwort / Ergebnis festgelegt, die sie als festgelegt gültig macht.

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 eine leere Zeichenfolge gesendet wurde. Das ist die Grundlogik für das Verständnis von NULL.

Zusammenfassung

Es geht nicht darum, verrückte Funktionen zu erstellen, um das Problem zu umgehen, sondern nur darum, wie Ihr Gehirn NULL betrachtet. Wenn es NULL ist, nehmen Sie an, dass es nicht als irgendetwas festgelegt ist. Wenn Sie Variablen vordefinieren, definieren Sie sie je nach Art der Verwendung, die Sie für sie beabsichtigen, als 0, FALSE oder "" vordefinieren.

Fühlen Sie sich frei, dies zu zitieren. Es ist aus meinem logischen Kopf :)

großartig
quelle
5
Gute Antwort. So oft sehe ich Leute darüber schimpfen, wie sie dieses oder jenes Merkmal einer Sprache hassen. Aber sie scheinen anzunehmen, dass "wenn es nicht auf MEINE Weise funktioniert, dann ist es kaputt". Ja, es gibt schlechte Designentscheidungen. Es gibt aber auch sehr engstirnige Entwickler!
Curtisdf
23
Es gibt einen RIESIGEN Unterschied zwischen nicht gesetzter Variable und Variable === null. Einer existiert nicht, der andere hat den Wert null. Argumente, die null bedeuten, dass kein Wert einfach nicht wahr ist. Null ist ein Wert vom Typ Null. Es ist ein vollkommen gültiger Wert und es gibt keinen Grund für PHP, ihn als nicht existierenden Wert zu behandeln, was es leider tut. Es wäre in Ordnung, wenn nicht vorhandene Variablen null wären und jede vorhandene Variable nicht null wäre und das Zuweisen von null zur Variablen sie deaktivieren würde. Es gibt jedoch VIELE Situationen, in denen Funktionen als tatsächlichen Wert null zurückgeben. Dann sind wir durcheinander, weil es keinen blutigen Weg gibt, es zu testen.
Enrey
2
Ich weiß, wir sollten "nicht" die Existenz von Variablen in PHP überprüfen, verdammt, es gibt nicht einmal einen wirklichen Weg, dies zu überprüfen. Ich werde keinen Code schreiben, der davon abhängt, weil es in PHP nicht möglich ist. Das ist eine Einschränkung von PHP. Es gibt eindeutig einen Unterschied zwischen nicht gesetzten und Null-Variablen, aber PHP bietet keine Möglichkeit, diese zu unterscheiden. Viele Metafunktionen hängen jedoch intern davon ab: Das Lesen nicht vorhandener Variablen führt zu einer Benachrichtigung, isset($a['x'])die Ihnen falsch sagt, wenn sie xnull sind, und dennoch in ... count($a)angezeigt compactwird. Funktioniert für alle festgelegten Variablen, einschließlich nullsund so weiter.
Enrey
3
Diese Antwort ist in einem wesentlichen Punkt fehlerhaft: In der OO-Programmierung ist null die logische Wahl für "kein Objekt". Unter außergewöhnlichen Umständen, wenn eine Funktion ein Objekt oder kein Objekt zurückgeben kann, ist null die naheliegende Wahl. Technisch gesehen könnte in PHP false oder ein anderer Wert verwendet werden, der im booleschen Kontext als false angesehen wird, aber dann verlieren Sie etwas semantische Reinheit. Daher ist null ein durchaus vernünftiger Wert, um eine Variable so zu initialisieren, dass sie schließlich ein Objekt enthalten sollte, da sie für das relevant ist, was sie werden soll.
Chazomaticus
3
Solange PHP Fehler für undefinierte Variablen auslöst, jedoch nicht für null, gibt es einen Unterschied. Wenn null und undefined wirklich dasselbe Konzept sind, sollte PHP die undefinierten / nicht deklarierten Standardvariablen auf null setzen und niemals einen Fehler auslösen, aber niemand will das, weil es ein Entwicklungsalptraum ist. Null und undefiniert unterscheiden sich im Kontext der Wertesemantik möglicherweise nicht wirklich, aber sie unterscheiden sich stark, wenn es darum geht, klaren und debuggbaren Code zu schreiben.
Chris Middleton
9

Objekteigenschaften können von property_exists auf Existenz überprü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");
    }
}

quelle
4

Als Ergänzung zu greatbigmassives Diskussion darüber, was NULL bedeutet , 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 was noch wichtiger ist, es erklärt seinen Umfang . Eine Variable "existiert" überall in ihrem Geltungsbereich und nirgendwo außerhalb - sei es eine ganze Funktion oder ein einzelner "Block".

Innerhalb ihres Bereichs weist eine Variable einer Bezeichnung, die Sie als Programmierer ausgewählt haben , eine Bedeutung zu . Außerhalb seines Geltungsbereichs ist dieses Etikett bedeutungslos (ob Sie dasselbe Etikett in einem anderen Geltungsbereich verwenden, ist grundsätzlich irrelevant).

In PHP müssen Variablen nicht deklariert werden - sie werden lebendig, sobald Sie sie benötigen. Wenn Sie zum ersten Mal in eine Variable schreiben, weist PHP dieser Variablen einen Speichereintrag zu. Wenn Sie aus einer Variablen lesen, die derzeit keinen Eintrag hat, betrachtet PHP diese Variable als wertvoll NULL.

Automatische Codequalitätsdetektoren warnen Sie jedoch im Allgemeinen, wenn Sie eine Variable verwenden, ohne sie zuerst zu "initialisieren". Erstens hilft dies dabei, Tippfehler zu erkennen, z. B. das Zuweisen von, $thingIdaber das Lesen von$thing_id ; aber zweitens zwingt es Sie, den Umfang zu betrachten, über den diese Variable Bedeutung hat, genau wie es eine Deklaration tun würde.

Jeder Code, der sich darum kümmert, ob eine Variable "existiert", ist Teil des Gültigkeitsbereichs dieser Variablen. Unabhängig davon, ob sie initialisiert wurde oder nicht, haben Sie als Programmierer dieser Bezeichnung an dieser Stelle des Codes eine Bedeutung gegeben. 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 Code wie folgt 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 testen, ob es einen Schlüssel enthält array_key_exists().

Sie können Objekte auch auf ähnliche Weise verwenden und Eigenschaften dynamisch festlegen. In diesem Fall können Sie sie property_exists()genauso verwenden. Natürlich, wenn Sie eine Klasse definieren, können Sie erklären , welche Eigenschaften es hat - Sie können sogar die Wahl zwischen public, privateund protectedAnwendungsbereich.

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 angegeben wurde unset()), und einer Variablen null, deren Wert ist , gibt jeder Code, der diesen Unterschied für sinnvoll hält verwendet Variablen so, dass sie nicht verwendet werden sollen.

IMSoP
quelle
1
Sehr gute Punkte, aber nicht gerade eine Antwort auf die Frage.
Chazomaticus
1
Auf die explizite Frage "Wie sollen wir zuverlässig prüfen, ob eine Variable in PHP vorhanden ist?" Meine Antwort lautet "Du bist es nicht und hier ist der Grund". Sowohl diese Antwort als auch die von Greatbigmassive beantworten auch die implizite Frage "Warum isset()verhält es sich so?".
IMSoP
"Wenn Sie aus einer Variablen lesen, die derzeit keinen Eintrag hat, betrachtet PHP diese Variable als NULL." Das ist falsch. Eine undefinierte Variable ist einfach undefiniert. Es kann null zurückgeben, wenn Sie versuchen, darauf zuzugreifen, aber das ist irrelevant.
Hugo Zink
@HugoZink Irrelevant für was? Jeder Test, den Sie mit dem Wert einer undefinierten Variablen durchführen, zeigt Ihnen, dass der Wert ist null. Ob dieser Wert existiert, bevor Sie ihn betrachten, ist eine Frage für Philosophen, aber was beobachtbares Verhalten betrifft, ist der Wert konsistent null.
IMSoP
3

issetprü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 Geltungsbereich dieser Funktion. Es gibt keine angemessene Problemumgehung, um festzustellen, ob eine Variable NULL ist, weil sie nicht festgelegt ist oder weil sie 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
Salman A.
quelle
2

Ich stimme Ihrer Argumentation zu NULL nicht zu , und zu sagen, dass Sie Ihre Einstellung zu NULL ändern müssen, ist einfach seltsam.

Ich denke, isset () wurde nicht richtig entworfen. Isset () sollte Ihnen mitteilen, ob die Variable gesetzt wurde, und es sollte sich nicht um den tatsächlichen Wert der Variablen handeln.

Was ist, wenn Sie Werte überprüfen, die von einer Datenbank zurückgegeben wurden, und eine der Spalten einen NULL-Wert hat? Sie möchten dennoch wissen, ob dieser vorhanden ist, auch wenn der Wert NULL ist. Nein, vertrauen Sie 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 konzipiert sein, dass es so funktioniert:

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

Auf diese Weise überlassen wir es dem Programmierer, die Typen zu überprüfen, und überlassen es nicht isset (), anzunehmen, dass es nicht vorhanden ist, weil der Wert NULL ist - es ist einfach dummes Design

Christof Coetzee
quelle
In Ihrem Beispiel wird nicht die Existenz einer Variablen überprüft, sondern eines Array-Schlüssels. Eine Lösung dafür gibt es in Form von array_key_exists. Sie sollten sich niemals in einer Situation befinden, in der Sie zur Laufzeit nicht wissen, ob eine tatsächliche Variable vorhanden ist.
IMSoP
@chazomaticus Nun, Sie sollten sich niemals in einer Situation befinden, in der register_globals aktiviert ist, also stehe ich zu dieser Aussage.
IMSoP
Oh, ich stimme zu. Dennoch kann nicht jeder steuern, wo sein Code bereitgestellt wird. Es ist nützlich, Informationen für jede Situation zu haben, ob es so ist, wie es sein sollte oder nicht.
Chazomaticus
@chazomaticus Wenn Ihr Problem ist register_globals, dann ist Ihre Antwort keine Änderung an isset(). Das PHP-Handbuch erwähnt "es ist im Allgemeinen eine gute Programmierpraxis, Variablen zuerst zu initialisieren", was gelöst wirdregister_globals eher zur Entwurfszeit als zur Laufzeit gelöst wird. Es gibt auch einen FAQ-Eintrag , der eine unregister_globals()Funktion zur Bearbeitung zur Laufzeit enthält.
IMSoP
2

Ich werde dem schnell zwei Cent hinzufügen. Ein Grund für dieses verwirrende Problem ist, dass dieses Szenario das gleiche Ergebnis zu liefern scheint, wenn die Fehlerberichterstattung nicht vollständig ist:

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

Sie könnten von diesem Ergebnis annehmen, dass der Unterschied zwischen $a = nullund nicht definiert$b nichts ist.

Kurbelfehlermeldung:

NULL

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

Hinweis: Es wurde ein undefinierter Variablenfehler ausgegeben, aber der Ausgabewert von var_dumpist immer noch NULL.

PHP hat offensichtlich die 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 denke, die akzeptierte Antwort ist größtenteils gut, aber wenn ich sie implementieren würde, würde ich einen Wrapper dafür schreiben. Wie bereits in dieser Antwort erwähnt , muss ich zustimmen, dass ich nicht auf eine Situation gestoßen bin, 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 gesetzt, null, leer usw.). Um nicht zu sagen, dass eine solche Situation in Zukunft nicht mehr auftreten wird, aber da es ein ziemlich einzigartiges Problem zu sein scheint, wundert es mich nicht, dass sich die PHP-Entwickler nicht die Mühe gemacht haben, dies zu tun.

Robbie Averill
quelle
Die Warnung zu undefinierten Variablen ist ein Hinweis für den Programmierer, dass im Code etwas falsch gemacht wurde. Außerhalb des Debuggens (für das es Tools außerhalb der Sprache gibt) sollte es niemals erforderlich sein, dass ein Programm einen solchen Status erkennt, da der Programmierer immer wissen sollte, welche Variablen er deklariert.
IMSoP
1

Wenn ich Folgendes ausführe:

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

Ich erhalte eine Fehlermeldung:

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

Wenn ich Folgendes ausführe:

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

Ich verstehe den Fehler nicht.

Wenn ich eine Variable habe, die gesetzt werden soll, mache ich normalerweise Folgendes.

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

oder

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

Auf diese Weise kann ich später im Skript sicher $ foo verwenden und wissen, dass es "gesetzt" ist und standardmäßig null ist. Später kann ichif ( is_null($foo) ) { /* ... */ } wenn ich muss und sicher wissen, dass die Variable existiert, auch wenn sie null ist.

Die vollständige Isset-Dokumentation enthält etwas mehr als nur das, was ursprünglich eingefügt wurde. Ja, es gibt false für eine Variable zurück, die zuvor festgelegt wurde, jetzt aber null ist, aber es gibt auch false zurück, wenn eine Variable noch nicht festgelegt wurde (je) und für jede Variable, die als nicht festgelegt markiert wurde. Es wird auch darauf hingewiesen, dass das NULL-Byte ("\ 0") nicht als null betrachtet wird und true zurückgibt.

Bestimmen Sie, ob eine Variable gesetzt ist.

Wenn eine Variable mit unset () nicht gesetzt wurde, wird sie nicht mehr gesetzt. isset () gibt FALSE zurück, wenn eine Variable getestet wird, die auf NULL gesetzt wurde. Beachten Sie auch, dass ein NULL-Byte ("\ 0") nicht der PHP-NULL-Konstante entspricht.

Beau Simensen
quelle
Er hat die Dokumente von diesem Link entfernt. Lesen Sie den ersten Satz, den zweiten Absatz des Beschreibungsabschnitts über den von Ihnen angegebenen Link. Es ist genau das, was er oben zitiert hat.
Zoredache
Dies ist keine schlechte Vorgehensweise für einfache Skripte, aber in komplexen (z. B. großen OO) Projekten wird dies nicht mehr möglich. Wie oben erwähnt, gibt is_null () TRUE für Variablen zurück, die nicht festgelegt sind. Es gibt also keinen Grund, das zu tun, was Sie sagen, außer um eine PHP-Warnung zu vermeiden.
Chazomaticus
1
Warum sollte dies bei gut gestalteten "großen OO" -Projekten überhaupt ein Problem sein? Warum sollten Sie jemals $ foo in einem Methodenkörper haben, der möglicherweise nicht vor seiner ersten Verwendung festgelegt wurde?
Beau Simensen
1

Versuchen Sie es mit

unset($v)

Es scheint, dass eine Variable nur dann nicht gesetzt wird, wenn sie spezifisch nicht gesetzt ist ($ v). Es hört sich so an, als ob Ihre Bedeutung von "Existenz" sich von der Definition von PHP unterscheidet. NULL ist sicherlich vorhanden, es ist NULL.

Joe Phillips
quelle
Ich bin mir nicht sicher was du meinst. Wenn Sie ein Array mit einem Element 'a' haben, müssen Sie das Element 'b' nicht deaktivieren (), damit das Element 'b' in PHP nicht existiert. Es existiert einfach nicht. Gleiches gilt beispielsweise für globale Variablen, die Sie sich als Elemente des $ GLOBALS-Arrays vorstellen können.
Chazomaticus
1
Ich stimme jedoch zu, dass tatsächlich eine Variable mit einem NULL-Wert existiert.
Chazomaticus
0

Ich muss sagen, dass ich in all meinen Jahren der PHP-Programmierung nie ein Problem mit der isset()Rückgabe von false für eine Nullvariable hatte. OTOH, ich habe Probleme mit isset()einem Fehler bei einem Null-Array-Eintrag festgestellt - aberarray_key_exists() funktioniert in diesem Fall ordnungsgemäß.

Zum Vergleich definiert Icon eine nicht verwendete Variable explizit als Rückgabe, &nullsodass Sie den is-null-Test in Icon verwenden, um auch nach einer nicht gesetzten Variablen zu suchen. Das macht die Sache einfacher. Andererseits hat Visual BASIC mehrere Zustände für eine Variable, die keinen Wert hat (Null, Leer, Nichts, ...), und Sie müssen häufig nach mehr als einem suchen. Dies ist als Fehlerquelle bekannt.

staticsan
quelle
0

Gemäß dem PHP-Handbuch für die Funktion empty () gilt: "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. Leer () generiert keine Warnung, wenn die Variable existiert nicht. " (Meine Betonung.) Das bedeutet, dass die Funktion empty () gemäß dem Titel Frage als "beste Möglichkeit zum Testen der Existenz einer Variablen in PHP" gelten sollte.

Dies ist jedoch nicht gut genug, da die Funktion empty () durch eine vorhandene Variable getäuscht werden kann, die auf NULL gesetzt ist.

Ich unterbreche meine frühere Antwort, um etwas Besseres zu präsentieren, da dies weniger umständlich ist als meine ursprüngliche Antwort (die zum Vergleich auf diese Unterbrechung folgt).

  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
  }

Zwei einfache Codezeilen können die obige Funktion verwenden, um festzustellen, 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 diesen beiden Zeilen mit allen geeigneten Elementen folgen, z. B. diesem Beispiel:

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

Ich wollte den Aufruf von ob_start () und ($ testvar === null) innerhalb der Funktion setzen und die Variable einfach an die Funktion übergeben, aber es funktioniert nicht. Selbst wenn Sie versuchen, die Variable "Referenz übergeben" der Variablen zu verwenden, wird die Variable definiert, und die Funktion kann niemals erkennen, dass sie zuvor undefiniert war. Was hier vorgestellt wird, ist ein Kompromiss zwischen dem, was ich tun wollte und dem, was tatsächlich funktioniert.

Das Vorstehende impliziert, dass es eine andere Möglichkeit gibt, immer zu vermeiden, dass die Fehlermeldung "Undefinierte Variable" angezeigt wird. (Die Annahme hier ist, dass Sie verhindern möchten, dass eine solche Meldung getestet wird, um festzustellen, ob eine Variable undefiniert 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 tun:

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

Der Wert der neu instanziierten Variablen wird natürlich auf null gesetzt!

(Unterbrechung endet)

Nach einigem Lernen und Experimentieren funktioniert hier 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 "no error" initialisiert. Eine "Handlerfunktion" ist definiert. Wenn die $ testvar (die Variable, die wir wissen möchten, ob sie undefiniert ist oder nicht) den vorläufigen Funktionstest empty () 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, der, wenn er nicht definiert ist, einen Fehler auslöst. Die Handlerfunktion erfasst den Fehler und prüft speziell, ob der Grund für den Fehler darin besteht, dass die Variable undefiniert ist. Das Ergebnis wird in die Fehlerinformationsvariable $ er eingefügt, die wir später testen können, um zu tun, was wir wollen, da wir sicher wissen, ob $ testvar definiert wurde oder nicht. Da wir die Handlerfunktion nur für diesen eingeschränkten Zweck benötigen, stellen wir die ursprüngliche Fehlerbehandlungsfunktion wieder her. Die Funktion "myHndlr" muss nur einmal deklariert werden. Der andere Code kann an die für $ testvar oder jede andere Variable, die wir auf diese Weise testen möchten, geeigneten Stellen kopiert werden.

vernonner3voltazim
quelle
1
Wenn Sie eine Warnung vermeiden möchten, dass Ihre Variablen nicht deklariert wurden, besteht die Lösung darin, Ihren Code zu korrigieren, um sie ordnungsgemäß zu deklarieren. Ihre instFunktion ähnelt im Grunde dem @Fehlerunterdrückungsoperator: "Ich weiß, dass ich hier etwas falsch mache, aber ich möchte nur, dass diese Nachricht verschwindet, ohne die Funktionsweise meines Codes in irgendeiner Weise zu ändern."
IMSoP
Andererseits sind die Erkennungsmethoden genial, aber ich bin immer noch der festen Überzeugung, dass Sie sie niemals anders verwenden sollten, als die Warnmeldungen zu wiederholen, die sie abfangen. (Sie sollten wahrscheinlich klarstellen, dass für Ihre Ausgabepufferversion die Einstellung error_reporting high und display_errors aktiviert sein muss.)
IMSoP
0

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 Benachrichtigungen korrigieren, die unter anderem durch undefinierte Variablen, Konstanten, Array-Schlüssel und Klasseneigenschaften generiert werden. Sobald Sie dies getan haben, müssen Sie sich keine Gedanken mehr über den Unterschied zwischen null und nicht deklarierten Variablen machen, und die Mehrdeutigkeit verschwindet.

Aktivieren der Benachrichtigungsberichterstattung möglicherweise nicht in allen Situationen eine gute Alternative, aber es gibt gute Gründe, dies zu aktivieren:

Warum sollte ich E_NOTICE-Fehler beheben?

In meinem Fall war es mehr als ein Jahr, in einem Projekt ohne es zu arbeiten, aber ich war es gewohnt, vorsichtig mit der Deklaration von Variablen umzugehen, sodass der Übergang schnell ging.

mikl
quelle
0

Der einzige Weg zu wissen, ob eine Variable im aktuellen Bereich definiert $GLOBALSist ( nicht vertrauenswürdig), ist array_key_exists( 'var_name', get_defined_vars() ).

Kostas Podias
quelle
1
Ich denke, das haben viele andere vorher gesagt, oder irre ich mich?
Stephan Vierkant
-1

Ich bevorzuge es, nicht leer als beste Methode zu verwenden, um zu überprüfen, ob eine Variable existiert, die a) existiert und b) nicht null ist.

if (!empty($variable)) do_something();
Hal
quelle
2
empty()nicht zu überprüfen , ob die Variable Null ist, es überprüft , ob es falsch-y ist, beispielsweise nicht einer der ""(eine leere Zeichenkette), 0(0 als eine ganze Zahl), 0.0(0 als float), "0"(0 als String) NULL, FALSE, array()(ein leeres Array) und $var;(eine deklarierte Variable, jedoch ohne Wert). Angenommen, Sie haben ein erforderliches Funkfeld in einer Form mit zwei Eingängen mit den Werten 0und 1. Wenn Sie empty()zur Validierung verwenden und der Benutzer 0dasjenige auswählt , wird versehentlich der Fehler "Erforderliches Feld darf nicht leer sein" angezeigt. Siehe das Handbuch php.net/manual/en/function.empty.php
Halil Özgür