Warum betrachtet PHP 0 als gleich einem String?

Lesezeit: 7 Minuten

Warum betrachtet PHP 0 als gleich einem String
Sergio Domingues

Ich habe das folgende Stück Code:

$item['price'] = 0;
/* Code to get item information goes in here */
if($item['price'] == 'e') {
    $item['price'] = -1;
}

Es ist beabsichtigt, den Artikelpreis auf 0 zu initialisieren und dann Informationen darüber zu erhalten. Wenn der Preis als „e“ angegeben wird, bedeutet dies einen Tausch anstelle eines Verkaufs, der als negative Zahl in einer Datenbank gespeichert wird.

Es besteht auch die Möglichkeit, den Preis auf 0 zu belassen, entweder weil der Artikel ein Bonus ist oder weil der Preis zu einem späteren Zeitpunkt festgelegt wird.

Aber immer wenn der Preis nicht festgelegt ist, was ihn mit dem Anfangswert von 0 belässt, wird die if Die oben angegebene Schleife wird als wahr ausgewertet und der Preis wird auf -1 gesetzt. Das heißt, es betrachtet 0 als gleich ‘e’.

Wie lässt sich das erklären?

Wenn der Preis als 0 angegeben wird (nach der Initialisierung), ist das Verhalten unberechenbar: manchmal wird if als wahr ausgewertet, manchmal als falsch.*

  • Ich habe festgestellt, dass die Verwendung von triple === anstelle von double == das erwartete Verhalten ergibt. Aber es ist trotzdem seltsam.

    – Sergio Domingues

    27. Juli 2011 um 10:46 Uhr

  • (Hinweis) ausreichend erklärt im PHP-Handbuch im Kapitel Geben Sie Jonglieren ein und abgebildet in der Typenvergleichstabelle

    – Gordon

    27. Juli 2011 um 10:56 Uhr


  • Wenn der einzig mögliche Zeichenfolgentyp „e“ ist, können Sie nicht einfach eine is_string($item[“price”]) prüfen? Das wäre etwas effizienter als ===. [citation needed]

    – Jimmie Lin

    27. Juli 2011 um 11:54 Uhr

  • in schwache Vergleiche zwischen String und Integer Die Zeichenfolge wird in eine Ganzzahl konvertiert (anstatt dass die Ganzzahl in eine Zeichenfolge “befördert” wird). if((string)$item['price'] == 'e') behebt das seltsame Verhalten. Siehe stackoverflow.com/a/48912540/1579327 für mehr Details

    – Paulo

    21. Februar 2018 um 18:08 Uhr


  • Bitte beachten Sie einen weiteren Fall in den Kommentaren unten von @Paolo, bei dem 0 (Ganzzahl) bei Verwendung des Double-Equals-Operators gleich jeder anderen Zeichenfolge ist.

    – Haitham Sweilem

    24. Juni 2018 um 16:30 Uhr

Warum betrachtet PHP 0 als gleich einem String
Nanne

Du machst == die die Typen für Sie aussortiert.

0 ist ein int, also wird es in diesem Fall gecastet 'e' zu einem int. Was nicht als eins parsbar ist und werden wird 0. Ein Faden '0e' würde werden 0 und würde passen!

Verwenden ===

Von PHP.net:

Vergleiche zwischen Zeichenfolgen und Zahlen mit == und anderen nicht strengen Vergleichsoperatoren funktionieren derzeit, indem die Zeichenfolge in eine Zahl umgewandelt wird und anschließend ein Vergleich mit Ganzzahlen oder Gleitkommazahlen durchgeführt wird. Dies führt zu vielen überraschenden Vergleichsergebnissen, von denen das bemerkenswerteste ist, dass 0 == “foobar” wahr zurückgibt.

Dieses Verhalten wurde jedoch geändert PHP 8.0:

Beim Vergleich mit einer numerischen Zeichenfolge verwendet PHP 8 einen Zahlenvergleich. Andernfalls konvertiert es die Zahl in eine Zeichenfolge und verwendet einen Zeichenfolgenvergleich.

PHP7

0 == 'foobar' // true
0 == '' // true
4 == '4e' // true (4e is cast as a number and becomes 4)

PHP 8 wandelt Zahlen in Strings um, bevor Vergleiche durchgeführt werden

0 == 'foobar' // false
0 == '' // false
4 == '4e' // false ('4e' is considered non-numeric therefore 4 is cast as a string and becomes '4')

Dies ist eine große Änderung, daher wurde sie in einer neuen Haupt-PHP-Version implementiert. Diese Änderung unterbricht die Abwärtskompatibilität in Skripten, die vom alten Verhalten abhängen.

  • Ein weiterer Nachteil des lockeren Vergleichs.

    – MC Kaiser

    5. Oktober 2014 um 13:46 Uhr

  • Knifflig. Ich bin gerade auf dieses hier gestoßen und war erstaunt, warum Zeichenfolge == 0. Daran muss ich mich erinnern.

    – Grzegorz

    28. September 2016 um 17:42 Uhr

  • Kratzte mich auch an diesem Kopf, als ich String-Schlüssel durchschleifte, aber das Array hatte ein anfängliches Indexelement „Null“, das beim Vergleich des ersten String-Schlüssels immer wahr blieb. Ich war wie was? Wie um alles in der Welt hat diese Antwort das klargestellt! Ich bin überrascht, dass diese ganze Frage nicht EINE akzeptierte Antwort hat. Das zeigt nur, dass einige Fragesteller Idioten sind.

    – Unglaublicher Hut

    23. März 2018 um 21:04 Uhr

Dies liegt daran, wie PHP die Vergleichsoperation durchführt, die die == Vergleichsoperator bezeichnet:

Wenn Sie eine Zahl mit einer Zeichenkette vergleichen oder der Vergleich numerische Zeichenketten umfasst, wird jede Zeichenkette in eine Zahl umgewandelt und der Vergleich numerisch durchgeführt. […] Die Typkonvertierung findet nicht statt, wenn der Vergleich erfolgt === oder !== da dabei sowohl der Typ als auch der Wert verglichen werden.

Als erster Operand ist eine Zahl (0) und die zweite ist eine Zeichenfolge ('e'), wird der String ebenfalls in eine Zahl umgewandelt (siehe auch Tisch Vergleich mit verschiedenen Typen). Die Handbuchseite zum String-Datentyp definiert, wie die Umwandlung von Zeichenfolgen in Zahlen fertig:

Wenn eine Zeichenfolge in einem numerischen Kontext ausgewertet wird, werden der resultierende Wert und Typ wie folgt bestimmt.

Wenn die Zeichenfolge keines der Zeichen ‘.‘, ‘e‘, oder ‘E‘ und der numerische Wert passt in die Grenzen von Integer-Typen (wie definiert durch PHP_INT_MAX), wird die Zeichenfolge als Ganzzahl ausgewertet. In allen anderen Fällen wird es als Float ausgewertet.

In diesem Fall ist die Zeichenfolge 'e' und wird daher als Float ausgewertet:

Der Wert wird durch den Anfangsteil der Zeichenfolge angegeben. Wenn die Zeichenfolge mit gültigen numerischen Daten beginnt, ist dies der verwendete Wert. Andernfalls wird der Wert sein 0 (Null). Gültige numerische Daten sind ein optionales Vorzeichen, gefolgt von einer oder mehreren Ziffern (die optional einen Dezimalpunkt enthalten), gefolgt von einem optionalen Exponenten. Der Exponent ist ein ‘e‘ oder ‘E‘ gefolgt von einer oder mehreren Ziffern.

Als 'e' nicht mit gültigen numerischen Daten beginnt, wird es als Float ausgewertet 0.

  • php gestaltet fast alles so, dass es leicht vergleichbar ist, und wirft dann ein paar Fallstricke ein, nur um unseren Tag zu ruinieren. Dies passt nicht zur übrigen Designphilosophie von PHP. Wenn es keine Täuschung gibt, gibt es eine Philosophie???

    – Benutzer3338098

    30. Juli 2015 um 15:38 Uhr

  • zumal “e” auf true und “” auf false umwandelt

    – Benutzer3338098

    19. August 2015 um 21:15 Uhr

1646960048 966 Warum betrachtet PHP 0 als gleich einem String
Paolo

"ABC" == 0

bewertet true da Erste "ABC" wird in eine Ganzzahl umgewandelt und wird 0 dann es wird verglichen mit 0.

Das ist ein seltsam Verhalten der PHP-Sprache: normalerweise würde man erwarten 0 zum String befördert werden "0" und dann verglichen mit "ABC" mit einem Ergebnis false. Vielleicht passiert das in anderen Sprachen wie JavaScript, wo der schwache Vergleich "ABC" == 0 bewertet false.

Ein strenger Vergleich löst das Problem:

"ABC" === 0

bewertet false.

Aber Was ist, wenn ich Zahlen als Zeichenfolgen mit Zahlen vergleichen muss?

"123" === 123

bewertet false weil linker und rechter Term von unterschiedlichem Typ sind.

Was tatsächlich benötigt wird, ist ein schwacher Vergleich ohne die Fallstricke des Jonglierens von PHP-Typen.

Die Lösung besteht darin, die Terme explizit zu Strings hochzustufen und dann einen Vergleich durchzuführen (streng oder schwach spielt keine Rolle mehr).

(string)"123" === (string)123

ist

true

während

(string)"123" === (string)0

ist

false


Auf den Originalcode angewendet:

$item['price'] = 0;
/*code to get item information goes in here*/
if((string)$item['price'] == 'e') {
    $item['price'] = -1;
}

1646960049 779 Warum betrachtet PHP 0 als gleich einem String
Vincent Mimoun-Prat

Der Operator == versucht, Werte abzugleichen, auch wenn sie unterschiedlichen Typs sind. Zum Beispiel:

'0' == 0 will be true

Wenn Sie auch einen Typvergleich benötigen, verwenden Sie den Operator ===:

'0' === 0 will be false

1646960049 771 Warum betrachtet PHP 0 als gleich einem String
Sebastian Renauld

Ihr Problem ist der doppelte Gleichheitsoperator, der das rechte Mitglied in den Typ des linken umwandelt. Verwenden Sie strict, wenn Sie dies vorziehen.

if($item['price'] == 'e') {
    $item['price'] = -1;
}

Kommen wir zurück zu Ihrem Code (oben kopiert). In diesem Fall in den meisten Fällen $item[‘price’] eine Ganzzahl ist (außer natürlich, wenn sie gleich e ist). Als solches wird PHP nach den Gesetzen von PHP typisieren "e" zu Integer, was ergibt int(0). (Glaubst du mir nicht? <?php $i="e"; echo (int)$i; ?>).

Um dies einfach zu umgehen, verwenden Sie den Triple-Equal-Operator (exakter Vergleich), der den Typ überprüft und nicht implizit typisiert.

PS: ein PHP Fun Fact: a == b bedeutet das nicht b == a. Nehmen Sie Ihr Beispiel und kehren Sie es um: if ("e" == $item['price']) wird niemals tatsächlich erfüllt, vorausgesetzt, dass $item[‘price’] ist immer eine ganze Zahl.

Warum betrachtet PHP 0 als gleich einem String
Jim Morrison

Es gibt eine ziemlich praktische Methode in PHP, um eine Mischung aus “0”, “false”, “off” als == false und “1”, “on”, “true” als == true zu validieren, was oft übersehen wird. Es ist besonders nützlich zum Analysieren von GET/POST-Argumenten:

filter_var( $item['price'], FILTER_VALIDATE_BOOLEAN );

Es ist für diesen Anwendungsfall nicht ganz relevant, aber angesichts der Ähnlichkeit und Tatsache, dass dies das Ergebnis der Suche ist, das tendenziell gefunden wird, wenn die Frage gestellt wird, ob (String) “0” als falsch validiert werden soll, dachte ich, es würde anderen helfen.

http://www.php.net/manual/en/filter.filters.validate.php

Du solltest benutzen === anstatt ==, da der gewöhnliche Operator die Typen nicht vergleicht. Stattdessen wird versucht, die Elemente zu typisieren.

Inzwischen die === berücksichtigt die Art der Artikel.

  • === bedeutet “gleich”,
  • == bedeutet “eeeeh .. sieht irgendwie aus wie”

  • Ich verstehe. Das funktioniert jetzt (mit einem Typecast): if((string)$item['price']=='e'){ $item['price'] = -1; }

    – Sergio Domingues

    27. Juli 2011 um 10:54 Uhr

  • aber das solltest du nicht tun. Verwenden Sie einfach die === Operator

    – teresko

    27. Juli 2011 um 11:23 Uhr

989440cookie-checkWarum betrachtet PHP 0 als gleich einem String?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy