## 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.

Vergleichsoperatoren
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.

Warnung

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 mit PHP 7 folgende Ausgabe:

    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

Beispiel #1 Vergleichsoperatoren

    <?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).

Vergleich mit verschiedenen Typen
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 #2 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 #3 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
    }
    ?>

Warnung

# 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.

### Siehe auch

- strcasecmp()
- strcmp()
- Array-Operatoren
- Typen

### Ternärer Operator

Ein weiterer Vergleichs-Operator ist der "?:" (oder ternäre) Operator.

Beispiel #4 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'];
    }

    ?>

Der Ausdruck `(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 #5 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 #6 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 #7 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';
    }
    ?>

Der Ausdruck `(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 #8 Verschachtelung des null-Koaleszenz-Operators

>     <?php

>     $foo = null;
>     $bar = null;
>     $baz = 1;
>     $qux = 2;

>     echo $foo ?? $bar ?? $baz ?? $qux; // gibt 1 aus

>     ?>

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open