PHP 8.3.4 Released!

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

<?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 #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
}
?>

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.

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

?>
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 #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';
}
?>
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 #7 Verschachtelung des null-Koaleszenz-Operators

<?php

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

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

?>

add a note

User Contributed Notes 13 notes

up
174
crazy888s at hotmail dot com
14 years ago
I couldn't find much info on stacking the new ternary operator, so I ran some tests:

<?php
echo 0 ?: 1 ?: 2 ?: 3; //1
echo 1 ?: 0 ?: 3 ?: 2; //1
echo 2 ?: 1 ?: 0 ?: 3; //2
echo 3 ?: 2 ?: 1 ?: 0; //3

echo 0 ?: 1 ?: 2 ?: 3; //1
echo 0 ?: 0 ?: 2 ?: 3; //2
echo 0 ?: 0 ?: 0 ?: 3; //3
?>

It works just as expected, returning the first non-false value within a group of expressions.
up
8
admin at zeros dot co dot id
1 year ago
Please be careful when you try to compare strings that have a plus sign `+` at the beginning (such as phone number, etc). When you use the Equal operator `==` PHP will ignore the plus sign. Use Identical operator `===` instead

Example:

$str1 = "62";
$str2 = "+62";

var_dump($str1 == $str2); // bool(true)
var_dump($str1 === $str2); // bool(false)
up
5
Sumon Mahmud
4 years ago
Extending from here: https://www.php.net/manual/en/language.operators.comparison.php#121907

$a = ['a' => 1, 'b' => 2, 'c' => 3, 'e' => 4];
$b = ['a' => 1, 'b' => 2, 'd' => 3, 'e' => 4];

echo $a > $b; // 0
echo $b > $a; // 0
echo $a <$b; // 0
echo $b < $a; // 0

If using spaceship operator then it is returning true like :

echo $a <=> $b; //1
echo $b <=> $a; //1
echo $a <=> $b; //1
echo $b <=> $a; //1
up
24
adam at caucho dot com
17 years ago
Note: according to the spec, PHP's comparison operators are not transitive. For example, the following are all true in PHP5:

"11" < "a" < 2 < "11"

As a result, the outcome of sorting an array depends on the order the elements appear in the pre-sort array. The following code will dump out two arrays with *different* orderings:

<?php
$a
= array(2, "a", "11", 2);
$b = array(2, "11", "a", 2);
sort($a);
var_dump($a);
sort($b);
var_dump($b);
?>

This is not a bug report -- given the spec on this documentation page, what PHP does is "correct". But that may not be what was intended...
up
8
Tahazzot
2 years ago
Very careful when reading PHP documentation, Here's a lot of miss information.

According to documentation, They say's (int) 0 == (string) "a" is true. But it is not in PHP 8.

var_dump(0 == "a"); // 0 == 0 -> true

Now In PHP 8 it's False.
up
18
rshawiii at yahoo dot com
18 years ago
You can't just compare two arrays with the === operator
like you would think to find out if they are equal or not. This is more complicated when you have multi-dimensional arrays. Here is a recursive comparison function.

<?php
/**
* Compares two arrays to see if they contain the same values. Returns TRUE or FALSE.
* usefull for determining if a record or block of data was modified (perhaps by user input)
* prior to setting a "date_last_updated" or skipping updating the db in the case of no change.
*
* @param array $a1
* @param array $a2
* @return boolean
*/
function array_compare_recursive($a1, $a2)
{
if (!(
is_array($a1) and (is_array($a2)))) { return FALSE;}

if (!
count($a1) == count($a2))
{
return
FALSE; // arrays don't have same number of entries
}

foreach (
$a1 as $key => $val)
{
if (!
array_key_exists($key, $a2))
{return
FALSE; // uncomparable array keys don't match
}
elseif (
is_array($val) and is_array($a2[$key])) // if both entries are arrays then compare recursive
{if (!array_compare_recursive($val,$a2[$key])) return FALSE;
}
elseif (!(
$val === $a2[$key])) // compare entries must be of same type.
{return FALSE;
}
}
return
TRUE; // $a1 === $a2
}
?>
up
13
bishop
17 years ago
When you want to know if two arrays contain the same values, regardless of the values' order, you cannot use "==" or "===". In other words:

<?php
(array(1,2) == array(2,1)) === false;
?>

To answer that question, use:

<?php
function array_equal($a, $b) {
return (
is_array($a) && is_array($b) && array_diff($a, $b) === array_diff($b, $a));
}
?>

A related, but more strict problem, is if you need to ensure that two arrays contain the same key=>value pairs, regardless of the order of the pairs. In that case, use:

<?php
function array_identical($a, $b) {
return (
is_array($a) && is_array($b) && array_diff_assoc($a, $b) === array_diff_assoc($b, $a));
}
?>

Example:
<?php
$a
= array (2, 1);
$b = array (1, 2);
// true === array_equal($a, $b);
// false === array_identical($a, $b);

$a = array ('a' => 2, 'b' => 1);
$b = array ('b' => 1, 'a' => 2);
// true === array_identical($a, $b)
// true === array_equal($a, $b)
?>

(See also the solution "rshawiii at yahoo dot com" posted)
up
2
gfilippakis at sleed dot gr
11 months ago
Please note that using the null coalescing operator to check properties on a class that has the __get magic method (without an __isset magic method) invokes the magic method.

For example:

<?php

class A
{
public function
__get($property)
{
echo
'Called __get for ' . $property . PHP_EOL;
}
}

$a = new A();

echo
'Trying null coalescing operator' . PHP_EOL;
$b = $a->test ?? 5;

echo
'Trying isset()' . PHP_EOL;
if (isset(
$a->test)) {
$b = $a->test;
} else {
$b = 5;
}

?>
up
1
Hayley Watson
7 months ago
Between the "shortcut ternary" (aka "elvis") and "spaceship" operators, you can write some quite compact comparison functions for usort and its ilk.

If you want to sort an array of associative arrays by several different keys you can chain them in the same way that you can list column names in an SQL ORDER BY clause.

<?php
usort
($array, fn($a, $b) => $a['a'] <=> $b['a']
?:
$b['b'] <=> $a['b']
?:
$a['c'] <=> $b['c']);
?>
Will sort the array by column 'a', then by column 'b' descending, then by column 'c'; or in SQL-speak 'ORDER BY a, b DESC, c".
up
5
Marcin Kuzawiski
8 years ago
A < B and still B < A...

$A = [1 => 1, 2 => 0, 3 => 1];
$B = [1 => 1, 3 => 0, 2 => 1];

var_dump($A < $B); // TRUE
var_dump($B < $A); // TRUE

var_dump($A > $B); // TRUE
var_dump($B > $A); // TRUE

Next - C and D are comparable, but neither C < D nor D < C (and still C != D)...

$C = [1 => 1, 2 => 1, 3 => 0];
$D = [1 => 1, 3 => 1, 2 => 0];

var_dump($C < $D); // FALSE
var_dump($D < $C); // FALSE

var_dump($C > $D); // FALSE
var_dump($D > $C); // FALSE

var_dump($D == $C); // FALSE
up
4
niall at maranelda dot org
6 years ago
Care must be taken when using the spaceship operator with arrays that do not have the same keys:

- Contrary to the notes above ("Example #2 Transcription of standard array comparison"), it does *not* return null if the left-hand array contains a key that the right-hand array does not.
- Because of this, the result depends on the order you do the comparison in.

For example:

<?php
$a
= ['a' => 1, 'b' => 2, 'c' => 3, 'e' => 4];
$b = ['a' => 1, 'b' => 2, 'd' => 3, 'e' => 4];

var_dump($a <=> $b); // int(1) : $a > $b because $a has the 'c' key and $b doesn't.

var_dump($b <=> $a); // int(1) : $b > $a because $b has the 'd' key and $a doesn't.
?>
up
2
Ryan Mott
4 years ago
Searching for "double question mark" operator should find this page (and hopefully after this comment the crawlers will agree)
up
5
Cuong Huy To
12 years ago
In the table "Comparison with Various Types", please move the last line about "Object" to be above the line about "Array", since Object is considered to be greater than Array (tested on 5.3.3)

(Please remove my "Anonymous" post of the same content before. You could check IP to see that I forgot to type my name)
To Top