Ich habe mehrere ältere Anwendungen, die viele "xyz is undefined" - und "undefined offset" -Nachrichten auslösen, wenn sie auf der E_NOTICE-Fehlerebene ausgeführt werden, da das Vorhandensein von Variablen nicht explizit mit isset()
und consorts überprüft wird .
Ich denke darüber nach, sie durchzuarbeiten, um sie E_NOTICE-kompatibel zu machen, da Hinweise auf fehlende Variablen oder Offsets lebensrettend sein können, möglicherweise geringfügige Leistungsverbesserungen erzielt werden müssen und dies insgesamt sauberer ist.
Mir gefällt jedoch nicht, was das Zufügen von Hunderten von isset()
empty()
und array_key_exists()
s mit meinem Code bewirkt. Es wird aufgebläht, weniger lesbar, ohne an Wert oder Bedeutung zu gewinnen.
Wie kann ich meinen Code ohne übermäßige Anzahl von Variablenprüfungen strukturieren und gleichzeitig E_NOTICE-kompatibel sein?
quelle
Antworten:
Für Interessenten habe ich dieses Thema zu einem kleinen Artikel erweitert, der die folgenden Informationen in einer etwas besser strukturierten Form enthält: Der endgültige Leitfaden für PHPs Isset und leer
IMHO sollten Sie darüber nachdenken, nicht nur die App "E_NOTICE kompatibel" zu machen, sondern das Ganze neu zu strukturieren. Mit Hunderten von Punkten in Ihrem Code , dass regelmäßig versucht Sounds inexistent Variablen wie ein eher schlecht strukturiertes Programm zu verwenden. Der Versuch, auf nicht vorhandene Variablen zuzugreifen, sollte niemals stattfinden. Andere Sprachen schrecken dies beim Kompilieren zurück. Die Tatsache, dass PHP es Ihnen ermöglicht, bedeutet nicht, dass Sie es tun sollten.
Diese Warnungen sollen Ihnen helfen, Sie nicht stören. Wenn Sie eine Warnung erhalten "Sie versuchen, mit etwas zu arbeiten, das es nicht gibt!" Ihre Reaktion sollte lauten: "Ups, mein Schlimmes, lassen Sie mich das so schnell wie möglich beheben." Wie sonst können Sie den Unterschied zwischen "Variablen, die gut und undefiniert funktionieren" und ehrlich falschem Code erkennen, der zu schwerwiegenden Fehlern führen kann ? Dies ist auch der Grund, warum Sie immer, immer mit einer Fehlerberichterstattung auf 11 entwickeln und Ihren Code so lange einstecken, bis kein einziger mehr vorhanden ist
NOTICE
ausgestellt wird. Das Deaktivieren der Fehlerberichterstattung gilt nur für Produktionsumgebungen, um Informationslecks zu vermeiden und eine bessere Benutzererfahrung auch bei fehlerhaftem Code zu erzielen.Um näher darauf einzugehen:
Sie benötigen immer
isset
oderempty
irgendwo in Ihrem Code. Die einzige Möglichkeit, deren Auftreten zu reduzieren, besteht darin, Ihre Variablen ordnungsgemäß zu initialisieren. Je nach Situation gibt es verschiedene Möglichkeiten, dies zu tun:Funktionsargumente:
Sie müssen nicht überprüfen, ob
$bar
oder$baz
sind sie in der Funktion festgelegt, da Sie sie nur festlegen. Sie müssen sich nur darum kümmern, ob ihr Wert zutrue
oderfalse
(oder was auch immer) ausgewertet wird .Regelmäßige Variablen überall:
Initialisieren Sie Ihre Variablen oben in einem Codeblock, in dem Sie sie verwenden möchten. Dies löst das
!isset
Problem, stellt sicher, dass Ihre Variablen immer einen bekannten Standardwert haben, gibt dem Leser eine Vorstellung davon, wie der folgende Code funktioniert, und dient somit auch als eine Art Selbstdokumentation.Arrays:
Auf die gleiche Weise wie oben initialisieren Sie das Array mit Standardwerten und überschreiben diese mit tatsächlichen Werten.
Nehmen wir in den verbleibenden Fällen eine Vorlage an, in der Sie Werte ausgeben, die möglicherweise von einem Controller festgelegt wurden oder nicht. Sie müssen lediglich Folgendes überprüfen:
Wenn Sie regelmäßig verwenden
array_key_exists
, sollten Sie bewerten, wofür Sie es verwenden. Das einzige Mal, dass es einen Unterschied macht, ist hier:Wie oben erwähnt, müssen Sie bei ordnungsgemäßer Initialisierung Ihrer Variablen nicht überprüfen, ob der Schlüssel vorhanden ist oder nicht, da Sie wissen, dass dies der Fall ist. Wenn Sie das Array von einer externen Quelle , wenn es darum, wird der Wert wahrscheinlich nicht sein ,
null
sondern''
,0
,'0'
,false
oder so ähnlich, dh einen Wert können Sie bewerten mitisset
oderempty
, abhängig von Ihrer Absicht. Wenn Sie regelmäßig einen Array Schlüssel gesetztnull
und wollen es alles bedeutet aberfalse
, dh wenn in dem obigen Beispiel der unterschiedlichen Ergebnisseisset
undarray_key_exists
einen Unterschied zu Ihrer Programmlogik zu machen, sollen Sie sich fragen , warum. Die bloße Existenz einer Variablen sollte nicht wichtig sein, nur ihr Wert sollte von Bedeutung sein. Wenn der Schlüssel eintrue
/false
flag ist, verwenden Sietrue
oderfalse
nichtnull
. Die einzige Ausnahme hiervon wären Bibliotheken von Drittanbietern, dienull
etwas bedeuten wollen , aber danull
es in PHP so schwer zu erkennen ist, muss ich noch eine Bibliothek finden, die dies tut.quelle
if ($array["xyz"])
stattisset()
oderarray_key_exists()
die ich etwas legitim, schon gar nicht strukturelle Probleme finden (korrigiert mich wenn ich mich nicht irre). Das Hinzufügenarray_key_exists()
sieht für mich wie eine schreckliche Verschwendung aus.array_key_exists
anstelle eines einfachenisset($array['key'])
oder verwenden würde!empty($array['key'])
. Sicher, beide fügen Ihrem Code 7 oder 8 Zeichen hinzu, aber ich würde das kaum als Problem bezeichnen. Es hilft auch, Ihren Code zu verdeutlichen:if (isset($array['key']))
bedeutet, dass diese Variable tatsächlich optional ist und möglicherweise nicht vorhanden ist, während sieif ($array['key'])
nur "wenn wahr" bedeutet. Wenn Sie eine Benachrichtigung für die letztere erhalten, wissen Sie, dass Ihre Logik irgendwo durcheinander ist.Schreiben Sie einfach eine Funktion dafür. Etwas wie:
die Sie als verwenden können
Machen Sie dasselbe für triviale Sachen wie
get_number()
,get_boolean()
,get_array()
und so weiter.quelle
<input name="something[]" />
. B. Eingaben mit . Dies würde zu Fehlern führen (da das Trimmen nicht auf Arrays angewendet werden kann), wenn der obige Code verwendet wird. In diesem Fall sollteis_string
und möglicherweise verwendet werdenstrval
. Dies ist nicht einfach ein Fall, in dem manget_array
entweder verwenden sollte, da Benutzereingaben (böswillig) möglicherweise irgendetwas und Benutzereingabe-Parser sowieso niemals Fehler auslösen sollten.Ich glaube, eine der besten Möglichkeiten, mit diesem Problem umzugehen, besteht darin, über eine Klasse auf Werte von GET- und POST-Arrays (COOKIE, SESSION usw.) zuzugreifen.
Erstellen Sie für jedes dieser Arrays eine Klasse und deklarieren Sie
__get
und__set
Methoden ( Überladung ).__get
akzeptiert ein Argument, das der Name eines Werts ist. Diese Methode sollte diesen Wert im entsprechenden globalen Array überprüfen, indem entwederisset()
oder verwendet wirdempty()
und der Wert zurückgegeben wird, falls vorhanden, odernull
(oder ein anderer Standardwert) anderweitig.Danach können Sie auf diese Weise sicher auf Array-Werte zugreifen:
$POST->username
und bei Bedarf eine Validierung durchführen, ohneisset()
s oderempty()
s zu verwenden. Wennusername
das entsprechende globale Array nicht vorhanden ist,null
wird es zurückgegeben, sodass keine Warnungen oder Benachrichtigungen generiert werden.quelle
Es macht mir nichts aus, die
array_key_exists()
Funktion zu benutzen . Tatsächlich bevorzuge ich die Verwendung dieser spezifischen Funktion, anstatt mich aufHack-Funktionen zu verlassen, die ihr Verhalten in Zukunft möglicherweise ändern,wie(durchgestrichen, um Anfälligkeiten zu vermeiden ).empty
undisset
Ich verwende jedoch eine einfache Funktion, die in dieser und einigen anderen Situationen beim Umgang mit Array-Indizes nützlich ist :
Angenommen, Sie haben die folgenden Arrays:
Wie bekommt man den "Wert" aus den Arrays? Einfach:
Wir haben bereits uni- und mehrdimensionale Arrays abgedeckt. Was können wir sonst noch tun?
Nehmen Sie zum Beispiel den folgenden Code:
Ziemlich langweilig, nicht wahr? Hier ist ein anderer Ansatz, der die
Value()
Funktion verwendet:Nehmen Sie
RealIP()
als zusätzliches Beispiel die Funktion für einen Test:Ordentlich, was? ;)
quelle
isset
undempty
sind Sprachkonstrukte , keine Funktionen. Zweitens, wenn Kernbibliotheksfunktionen / Sprachkonstrukte ihr Verhalten ändern, können Sie geschraubt werden oder nicht. Was ist, wennarray_key_exists
sich das Verhalten ändert? Die Antwort ist, dass dies nicht der Fall ist, solange Sie es wie dokumentiert verwenden. Undisset
ist dokumentiert, um genau so verwendet zu werden. Worst-Case-Funktionen sind in ein oder zwei Hauptversionen veraltet. NIH-Syndrom ist schlecht!array_key_exists()
zu prüfen, ob ein Schlüssel in einem Array vorhanden ist ?!array_key_exists()
wurde genau dafür erstellt , ich verlasse mich eher auf diesen Zweck alsisset()
und speziell,empty()
dessen offizielle Beschreibung lautet: "Bestimmen, ob eine Variable leer ist", erwähnt nichts, wenn sie tatsächlich existiert. Ihr Kommentar und Ihre Ablehnung sind eine der lächerlichsten, die ich den ganzen Monat gesehen habe .isset
und binempty
nicht mehr oder weniger zuverlässig alsarray_key_exists
und kann genau den gleichen Job machen. Ihr zweites, langwieriges Beispiel kann so geschrieben werden, dass$domain = isset($domain['host']) ? $domain['host'] : 'N/A';
nur Kernsprachenfunktionen, keine zusätzlichen Funktionsaufrufe oder Deklarationen erforderlich sind (beachten Sie, dass ich die Verwendung des ternären Operators jedoch nicht unbedingt befürworte; o)). Für gewöhnliche skalare Variablen müssen Sie nochisset
oder verwendenempty
, und Sie können sie für Arrays genauso verwenden. "Zuverlässigkeit" ist ein schlechter Grund, dies nicht zu tun.Ich bin mit Dir hier. Aber PHP-Designer haben viel schlimmere Fehler gemacht. Ohne eine benutzerdefinierte Funktion für das Lesen von Werten zu definieren, führt kein Weg daran vorbei.
quelle
params["width"] = params["width"] || 5
, Standardeinstellungen zu schreiben , anstatt all diesen Unsinn beiisset()
Aufrufen.register_globals
undmagic_quotes
. Die Probleme, die diese fördern, lassen nicht initialisierte Variablen im Vergleich fast harmlos erscheinen.Ich benutze diese Funktionen
Beispiele
quelle
Willkommen beim Null-Koaleszenz-Operator (PHP> = 7.0.1):
PHP sagt:
quelle
Erstellen Sie eine Funktion, die zurückgibt,
false
wenn sie nicht festgelegt ist, und, falls angegeben,false
leer ist. Wenn gültig, wird die Variable zurückgegeben. Sie können weitere Optionen hinzufügen, wie im folgenden Code dargestellt:quelle
Ich bin mir nicht sicher, wie Sie die Lesbarkeit definieren, aber die ordnungsgemäße Verwendung der Blöcke empty (), isset () und try / throw / catch ist für den gesamten Prozess ziemlich wichtig. Wenn Ihre E_NOTICE von $ _GET oder $ _POST stammt, sollten sie zusammen mit allen anderen Sicherheitsüberprüfungen, die diese Daten bestehen müssen, gegen empty () geprüft werden. Wenn es aus externen Feeds oder Bibliotheken stammt, sollte es in try / catch eingeschlossen werden. Wenn es aus der Datenbank stammt, sollte $ db_num_rows () oder ein gleichwertiges Element überprüft werden. Wenn es von internen Variablen stammt, sollten sie ordnungsgemäß initialisiert werden. Diese Arten von Benachrichtigungen stammen häufig aus der Zuweisung einer neuen Variablen zur Rückgabe einer Funktion, die bei einem Fehler FALSE zurückgibt. Diese sollten in einen Test eingeschlossen werden, der im Fehlerfall Sie können der Variablen entweder einen akzeptablen Standardwert zuweisen, den der Code verarbeiten kann, oder eine Ausnahme auslösen, die der Code verarbeiten kann. Diese Dinge verlängern den Code, fügen zusätzliche Blöcke hinzu und fügen zusätzliche Tests hinzu, aber ich stimme Ihnen nicht darin zu, dass sie auf jeden Fall einen zusätzlichen Mehrwert bieten.
quelle
Software wird nicht auf magische Weise von der Gnade Gottes ausgeführt. Wenn Sie etwas erwarten, das fehlt, müssen Sie es richtig handhaben.
Wenn Sie es ignorieren, schaffen Sie wahrscheinlich Sicherheitslücken in Ihren Anwendungen. In statischen Sprachen ist der Zugriff auf eine nicht definierte Variable einfach nicht möglich. Es wird Ihre Anwendung nicht einfach kompilieren oder zum Absturz bringen, wenn sie null ist.
Darüber hinaus ist Ihre Anwendung nicht mehr zu warten, und Sie werden verrückt, wenn unerwartete Dinge passieren. Sprachstrenge ist ein Muss und PHP ist von Natur aus in so vielen Aspekten falsch. Es macht Sie zu einem schlechten Programmierer, wenn Sie sich dessen nicht bewusst sind.
quelle
Was ist mit dem
@
Operator?Beispielsweise:
Sie können sagen, dass dies schlecht ist, weil Sie keine Kontrolle darüber haben, was "innerhalb" von $ foo passiert (wenn es sich beispielsweise um einen Funktionsaufruf handelt, der einen PHP-Fehler enthält). Wenn Sie diese Technik jedoch nur für Variablen verwenden, entspricht dies:
quelle
if(isset($foo))
ist eigentlich genug. Es wird zurückgegeben,TRUE
wenn der Ausdruck zu ausgewertet wirdTRUE
.