Vergleichs-Operatoren
Vergleichs-Operatoren erlauben es – wie der Name schon sagt – zwei Werte zu vergleichen. Wenn Sie an Beispielen verschiedener auf Typen bezogener Vergleiche interessiert sind, können Sie sich die PHP Typvergleich-Tabellen anschauen.
Beispiel | Name | Ergebnis |
---|---|---|
$a == $b | Gleich |
Gibt true zurück, wenn nach der Typumwandlung $a
gleich $b ist.
|
$a === $b | Identisch |
Gibt true zurück, wenn $a gleich
$b ist und beide denselben Typ haben.
|
$a != $b | Ungleich |
Gibt true zurück, wenn nach der Typumwandlung $a
nicht gleich $b ist.
|
$a <> $b | Ungleich |
Gibt true zurück, wenn nach der Typumwandlung $a
nicht gleich $b ist.
|
$a !== $b | Nicht identisch |
Gibt true zurück, wenn $a nicht gleich
$b ist, oder wenn beide nicht denselben Typ haben.
|
$a < $b | Kleiner als |
Gibt true zurück, wenn $a kleiner als
$b ist.
|
$a > $b | Größer als |
Gibt true zurück, wenn $a größer als
$b ist.
|
$a <= $b | Kleiner oder gleich |
Gibt true zurück, wenn $a kleiner oder gleich
$b ist.
|
$a >= $b | Größer oder gleich |
Gibt true zurück, wenn $a größer oder gleich
$b ist.
|
$a <=> $b | Raumschiff | Eine Ganzzahl (int), die kleiner als, gleich oder größer als 0 ist, wenn $a kleiner als, gleich oder größer als $b ist. |
Falls beide Operanden
numerische Zeichenketten
sind oder ein Operand eine Zahl ist und der andere eine
numerische Zeichenkette,
dann wird der Vergleich numerisch durchgeführt. Diese Regel gilt ebenfalls
für die switch-Anweisung.
Die Typumwandlung wird nicht durchgeführt, wenn der Vergleichsoperator
===
oder !==
ist, da hier sowohl der
Typ als auch der Wert verglichen werden.
Vor PHP 8.0.0 wurde bei einem Vergleich einer Zeichenkette mit einer Zahl oder einer numerischen Zeichenkette die Zeichenkette vor dem Vergleich in eine Zahl umgewandelt und der Vergleich numerisch durchgeführt.
<?php
var_dump(0 == "a");
var_dump("1" == "01");
var_dump("10" == "1e1");
var_dump(100 == "1e2");
switch ("a") {
case 0:
echo "0";
break;
case "a":
echo "a";
break;
}
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe mit PHP 7:
bool(true) bool(true) bool(true) bool(true) 0
Das oben gezeigte Beispiel erzeugt mit PHP 8 folgende Ausgabe:
bool(false) bool(true) bool(true) bool(true) a
<?php
// Ganzzahlen
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// Gleitkommazahlen
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// Zeichenketten
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
echo "a" <=> "aa"; // -1
echo "zz" <=> "aa"; // 1
// Arrays
echo [] <=> []; // 0
echo [1, 2, 3] <=> [1, 2, 3]; // 0
echo [1, 2, 3] <=> []; // 1
echo [1, 2, 3] <=> [1, 2, 1]; // 1
echo [1, 2, 3] <=> [1, 2, 4]; // -1
// Objekte
$a = (object) ["a" => "b"];
$b = (object) ["a" => "b"];
echo $a <=> $b; // 0
$a = (object) ["a" => "b"];
$b = (object) ["a" => "c"];
echo $a <=> $b; // -1
$a = (object) ["a" => "c"];
$b = (object) ["a" => "b"];
echo $a <=> $b; // 1
// nicht nur die Werte werden verglichen; die Schlüssel müssen übereinstimmen
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo $a <=> $b; // 1
?>
Für die verschiedenen Typen wird der Vergleich gemäß der folgenden Tabelle durchgeführt (in der angegebenen Reihenfolge).
Typ des 1. Operanden | Typ des 2. Operanden | Ergebnis |
---|---|---|
null oder string | string |
Umwandlung von null nach "", dann numerischer oder lexikalischer Vergleich
|
bool oder null | anything |
Umwandlung beider Werte nach bool, dann false < true
|
object | object | Eingebaute Klassen können eigene Vergleichsregeln definieren; verschiedene Klassen können nicht verglichen werden; für den Vergleich von Objekten derselben Klasse siehe Objektvergleiche |
string, resource, int oder float | string, resource, int oder float | Umwandlung von Zeichenketten und Ressourcen in Zahlen, dann numerischer Vergleich |
array | array | Das Array mit weniger Elementen ist kleiner; wird ein Schlüssel vom ersten Operanden nicht im zweiten gefunden, dann sind die Arrays nicht vergleichbar, andernfalls wird Element für Element verglichen (siehe folgendes Beispiel) |
object | anything | object ist immer größer |
array | anything | array ist immer größer |
Beispiel #1 Boolesche und null-Vergleiche
<?php
// Boolesche Werte und null werden immer als Boolesche Werte verglichen
var_dump(1 == TRUE); // TRUE - dasselbe wie (bool)1 == TRUE
var_dump(0 == FALSE); // TRUE - dasselbe wie (bool)0 == FALSE
var_dump(100 < TRUE); // FALSE - dasselbe wie (bool)100 < TRUE
var_dump(-10 < FALSE);// FALSE - dasselbe wie (bool)-10 < FALSE
var_dump(min(-100, -10, NULL, 10, 100)); // NULL - (bool)NULL < (bool)-100 ist FALSE < TRUE
?>
Beispiel #2 Umschreibung von Standard-Array-Vergleichen
<?php
// Arrays werden mit den normalen Vergleichsoperatoren sowie dem Raumschiff-Operator wie folgt verglichen
function standard_array_compare($op1, $op2)
{
if (count($op1) < count($op2)) {
return -1; // $op1 < $op2
} elseif (count($op1) > count($op2)) {
return 1; // $op1 > $op2
}
foreach ($op1 as $key => $val) {
if (!array_key_exists($key, $op2)) {
return 1;
} elseif ($val < $op2[$key]) {
return -1;
} elseif ($val > $op2[$key]) {
return 1;
}
}
return 0; // $op1 == $op2
}
?>
Vergleich von Gleitkommazahlen
Aufgrund der Art wie Gleitkommazahlen (float) intern dargestellt werden, sollten zwei Gleitkommazahlen nicht auf Gleichheit getestet werden.
Weitere Informationen sind der Dokumantation von float zu entnehmen.
Hinweis: Es ist wichtig zu beachten, dass die Typumwandlung von PHP nicht immer offensichtlich ist, wenn Werte unterschiedlichen Typs verglichen werden, insbesondere beim Vergleich von Integern mit Booleans oder Integern mit Strings. Daher ist es im Allgemeinen in den meisten Fällen ratsam,
===
und!==
für Vergleiche zu verwenden, anstatt==
und!=
.
Nicht vergleichbare Werte
Während der Identitätsvergleich (===
und
!==
) auf beliebige Werte angewendet werden kann,
sollten die anderen Vergleichsoperatoren nur auf vergleichbare Werte
angewandt werden. Wenn nicht vergleichbare Werte verglichen werden, ist
das Ergebnis undefiniert und sollte nicht als verlässlich eingestuft
werden.
Ternärer Operator
Ein weiterer Vergleichs-Operator ist der "?:" (oder ternäre) Operator.
Beispiel #3 Zuweisen eines Standardwerts
<?php
// Beispielanwendung für den ternären Operator
$action = (empty($_POST['action'])) ? 'standard' : $_POST['action'];
// Obiges ist mit dieser if/else-Anweisung identisch
if (empty($_POST['action'])) {
$action = 'standard';
} else {
$action = $_POST['action'];
}
?>
(ausdr1) ? (ausdr2) : (ausdr3)
wird zu ausdr2 ausgewertet, wenn
ausdr1 als true
ausgewertet wird, und zu
ausdr3, wenn
ausdr1 zu false
ausgewertet wird.
Beim ternären Operator kann der mittlere Teil weggelassen werden. Der
Ausdruck (ausdr1) ?: (ausdr3)
wird zum Ergebnis von
ausdr1 zurück, wenn
ausdr1 zu true
ausgewertet wird, und zu
ausdr3 andernfalls.
ausdr1 wird in diesem Fall nur einmal
ausgewertet.
Hinweis: Es ist zu beachten, dass der ternäre Operator ein Ausdruck ist und nicht als Variable, sondern als Wert eines Ausdrucks ausgewertet wird. Dies ist unbedingt zu berücksichtigen, wenn eine Variable per Referenz zurückgegeben werden soll. Die Anweisung
return $var == 42 ? $a : $b;
in einer Funktion, die per Referenz zurückgibt, wird daher nicht funktionieren und eine Warnung erzeugen.
Hinweis:
Es wird empfohlen, die "Verschachtelung" von ternären Ausdrücken zu vermeiden. Das Verhalten von PHP bei der Verwendung von mehr als einem nicht einkgeklammerten ternären Operator innerhalb eines einzigen Ausdrucks ist im Vergleich zu anderen Sprachen nicht eindeutig. In der Tat wurden ternäre Ausdrücke vor PHP 8.0.0 links-assoziativ (von links nach rechts) ausgewertet, und nicht rechts-assoziativ wie in den meisten anderen Programmiersprachen. Die Links-Assoziativität ist seit PHP 7.4.0 veraltet. Seit PHP 8.0.0 ist der ternäre Operator nicht-assoziativ.
Beispiel #4 Ungewöhnliches Verhalten des ternären Operators
<?php
// auf den ersten Blick scheint das folgende 'true' auszugeben
echo (true ? 'true' : false ? 't' : 'f');
// allerdings wird vor PHP 8.0.0 tatsächlich 't' ausgegeben
// das kommt daher, dass ternäre Ausdrücke links-assoziativ ausgewertet werden
// das Folgende ist eine augenfälligere Variante desselben Codes wie oben
echo ((true ? 'true' : false) ? 't' : 'f');
// hier kann man sehen, dass der erste Ausdruck zu 'true' ausgewertet wird,
// was wiederum zu (bool)true ausgewertet wird, und daher wird der Wahr-Zweig
// des zweiten ternären Ausdrucks zurückgegeben.
?>
Hinweis:
Die Verkettung von kurzen ternären Operatoren (
?:
) ist jedoch stabil und verhält sich plausibel. Sie wird zum ersten Argument ausgewertet, das einen nicht-falschen Wert ergibt. Es ist zu beachten, dass undefinierte Werte immer noch eine Warnung auslösen.Beispiel #5 Verkettung kurzer ternärer Operatoren
<?php
echo 0 ?: 1 ?: 2 ?: 3, PHP_EOL; //1
echo 0 ?: 0 ?: 2 ?: 3, PHP_EOL; //2
echo 0 ?: 0 ?: 0 ?: 3, PHP_EOL; //3
?>
Null-Koaleszens-Operator
Eine weitere nützliche Kurzform eines Operators ist der Operator "??" (null-Koaleszenz-Operator, etwa: Zuweisungsoperator für die Kombination mit null).
Beispiel #6 Zuweisung eines Standardwerts
<?php
// Beispiel für die Verwendung des null-Koaleszenz-Operators
$action = $_POST['action'] ?? 'standard';
// Obiges ist mit dieser if/else-Anweisung identisch
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else {
$action = 'standard';
}
?>
(ausdr1) ?? (ausdr2)
wird zu
ausdr2 ausgewertet, wenn
ausdr1 null
ist, und zu
ausdr1 andernfalls.
Insbesondere gibt dieser Operator keinen Hinweis und keine Warnung aus, wenn der Wert auf der linken Seite nicht existiert, genau wie isset(). Dies ist besonders für Array-Schlüssel nützlich.
Hinweis: Es ist zu beachten, dass der null-Koaleszenz-Operator ein Ausdruck ist und nicht als Variable, sondern als Wert eines Ausdrucks ausgewertet wird. Dies ist unbedingt zu berücksichtigen, wenn eine Variable per Referenz zurückgegeben werden soll. Die Anweisung
return $foo ?? $bar;
in einer Funktion, die per Referenz zurückgibt, wird daher nicht funktionieren, und eine Warnung erzeugen.
Hinweis:
Der null-Koaleszenz-Operator hat eine niedrige Priorität. Das heißt, wenn er mit anderen Operatoren (z. B. Verkettung von Zeichenketten oder arithmetische Operatoren) kombiniert wird, sind wahrscheinlich Klammern erforderlich.
<?php
// Löst die Warnung aus, dass $name undefiniert ist.
print 'Mr. ' . $name ?? 'Anonymous';
// Gibt "Mr. Anonymous" aus
print 'Mr. ' . ($name ?? 'Anonymous');
?>
Hinweis:
Es ist zu beachten, dass der null-Koaleszenz-Operator einfach verschachtelt werden kann:
Beispiel #7 Verschachtelung des null-Koaleszenz-Operators
<?php
$foo = null;
$bar = null;
$baz = 1;
$qux = 2;
echo $foo ?? $bar ?? $baz ?? $qux; // gibt 1 aus
?>