Операторы сравнения
PHP Manual
PHP Manual»Операторы»Сравнение

Операторы сравнения, как видно из названия, сравнивают между собой два значения. Интерес для знакомства также вызывают таблицы сравнения типов, поскольку показывают примеры сравнений, которые связаны с разными типами.

Операторы сравнения
Пример Название Результат
$a == $b Равно Возвращается true, если значение переменной $a после преобразования типов равно значению переменной $b.
$a === $b Тождественно равно Возвращается true, если значение переменной $a равно значению переменной $b и имеет тот же тип.
$a != $b Не равно Возвращается true, если значение переменной $a после преобразования типов не равно значению переменной $b.
$a <> $b Не равно Возвращается true, если значение переменной $a после преобразования типов не равно значению переменной $b.
$a !== $b Тождественно не равно Возвращается true, если значение переменной $a не равно значению переменной $b или они разных типов.
$a < $b Меньше Возвращается true, если значение переменной $a строго меньше значения переменной $b.
$a > $b Больше Возвращается true, если значение переменной $a строго больше значения переменной $b.
$a <= $b Меньше или равно Возвращается true, если значение переменной $a меньше или равно значению переменной $b.
$a >= $b Больше или равно Возвращается true, если значение переменной $a больше или равно значению переменной $b.
$a <=> $b Космический корабль (spaceship) Целое число (int) меньше, больше или равное нулю, когда значение переменной $a меньше, больше или равно значению переменной $b.

Сравнение выполняется численно, если оба операнда — числовые строки, или один операнд — число, а другой — числовая строка. Эти правила также справедливы для оператора switch. Типы не преобразовываются при сравнениях вида === или !==, поскольку это включает сравнение значения и типа.

Внимание

До PHP 8.0.0, если строка (string) сравнивалась с числом или числовой строкой, то перед выполнением сравнения строка (string) преобразовывалась в число. Это иногда давало неожиданные результаты, как видно в следующем примере:

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

?>

Результат выполнения приведённого примера в PHP 7:

bool(true)
bool(true)
bool(true)
bool(true)
0

Результат выполнения приведённого примера в PHP 8:

bool(false)
bool(true)
bool(true)
bool(true)
a

Пример #1 Операторы сравнения

<?php

// Целые числа
echo 1 <=> 1, ' '; // 0
echo 1 <=> 2, ' '; // -1
echo 2 <=> 1, ' '; // 1

// Числа с плавающей точкой
echo 1.5 <=> 1.5, ' '; // 0
echo 1.5 <=> 2.5, ' '; // -1
echo 2.5 <=> 1.5, ' '; // 1

// Строки
echo "a" <=> "a", ' '; // 0
echo "a" <=> "b", ' '; // -1
echo "b" <=> "a", ' '; // 1

echo "a" <=> "aa", ' ';  // -1
echo "zz" <=> "aa", ' '; // 1

// Массивы
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

// Объекты
$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

// Сравниваются не только значения; ключи тоже должны совпадать
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo $a <=> $b, ' '; // 1

?>

Для различных типов сравнение происходит в соответствии со следующей таблицей (по порядку).

Сравнение типов
Тип операнда 1 Тип операнда 2 Результат
null или string string Значение null преобразовывается в пустую строку (""), числовое или лексическое сравнение
bool или null значение любого типа Преобразуется в bool, false < true
object object Встроенные классы могут определять свои правила сравнения, объекты разных классов не сравниваются, про сравнение объектов одного класса рассказано в разделе «Сравнение объекта»
string, resource, int или float string, resource, int или float Строки и ресурсы переводятся в числа, обычная математика
array array Массив с меньшим количеством элементов меньше, если PHP не нашёл ключ из первого массива во втором массиве — массивы несравнимы, иначе идёт сравнение значения за значением (смотрите пример ниже)
array значение любого типа Тип array всегда больше
object значение любого типа Тип object всегда больше

Пример #2 Примеры сравнения boolean- и null-значений со значениями других типов

<?php

// Логические значения и null сравниваются как логические
var_dump(1 == TRUE); // TRUE  — то же, что и (bool) 1 == TRUE
var_dump(0 == FALSE); // TRUE  — то же, что и (bool) 0 == FALSE
var_dump(100 < TRUE); // FALSE  — то же, что и (bool) 100 < TRUE
var_dump(-10 < FALSE); // FALSE  — то же, что и (bool) -10 < FALSE
var_dump(min(-100, -10, NULL, 10, 100)); // NULL  — (bool) NULL < (bool) -100 это FALSE < TRUE

?>

Пример #3 Транскрипция стандартного сравнения массивов

<?php

// Массивы сравниваются как в этом примере — со стандартными операторами сравнения, и оператором «космический корабль» (spaceship).
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
}

Внимание

Сравнение чисел с плавающей точкой

Из-за внутреннего представления чисел с плавающей точкой (float) не нужно проверять два числа с плавающей точкой (float) на равенство.

Подробнее об этом рассказывает в документации к типу float.

Замечание: Когда пишут код, помнят, что жонглирование типами в PHP не всегда даёт предсказуемый результат при сравнении значений разных типов, особенно при сравнении целых чисел (int) с логическими значениями (bool) или целых чисел (int) со строками (string). Поэтому лучше пользоваться операторами === и !==, а не == и !=.

Несравнимые значение

Хотя тождественные сравнения === и !== применяют к произвольным значениям, другие операторы сравнения лучше применять только к сравнимым значениям. Результат сравнения несравнимых значений не определён и на него не нужно полагаться.

Тернарный оператор

Список условных операторов дополняет тернарный оператор «?:».

Пример #4 Присваивание значения по умолчанию

<?php

// Пример выражения с тернарным оператором
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];

// Код выше аналогичен блоку с конструкциями if/else
if (empty($_POST['action'])) {
    $action = 'default';
} else {
    $action = $_POST['action'];
}

?>
Выражение (expr1) ? (expr2) : (expr3) интерпретируется как expr2, если expr1 равно true, или как expr3, если expr1 равно false.

Можно не писать среднюю часть тернарного оператора. Выражение expr1 ?: expr3 оценивается как результат выражения expr1, если оно оценивается как true, иначе как результат выражения expr3. Выражение expr1 оценивается только один раз.

Замечание: Обратите внимание, что тернарный оператор — это выражение, и он оценивается не как переменная, а как результат выражения. Это важно, если нужно вернуть переменную по ссылке. Выражение return $var == 42 ? $a : $b; не будет работать в функции, возвращающей значение по ссылке, а в более поздних версиях PHP также будет выдано предупреждение.

Замечание:

Рекомендовано избегать «нагромождения» тернарных выражений. Поведение PHP при указании более чем одного тернарного оператора без скобок в одном выражении неочевидно в сравнении с другими языками. Впрямь, до PHP 8.0.0 троичные выражения оценивались как левоассоциативные, а не правоассоциативные, как в большей части других языков программирования. Опора на левую ассоциативность устарела начиная с PHP 7.4.0. Начиная с PHP 8.0.0 тернарный оператор неассоциативен.

Пример #5 Неочевидное поведение тернарного оператора

<?php

// Кажется, что следующий код выведет "true"
echo (true ? 'true' : false ? 't' : 'f');

// Однако код выводит "t" до PHP 8.0.0.
// Причина состоит в том, что тернарные выражения левоассоциативны

// Следующая запись — более очевидная версия приведённого кода
echo ((true ? 'true' : false) ? 't' : 'f');

// Здесь видно, что первое выражение оценивается как строковое "true", которое
// оценивается как логическое (bool) true, поэтому возвращает истинную ветвь
// второго тернарного выражения

?>

Замечание:

Цепочка коротких тернарных операторов (?:), однако, стабильна и ведёт себя обоснованно. Она будет оценивать первый аргумент, который оценивается как не ложное значение. Обратите внимание, что неопределённые значения все равно вызовут предупреждение.

Пример #6 Цепочка коротких тернарных операторов

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

Другой полезный сокращённый оператор — это оператор объединения с NULL — «??» (null coalescing).

Пример #7 Присваивание значения по умолчанию

<?php

// Пример работы с оператором нулевого слияния
$action = $_POST['action'] ?? 'default';

// Пример выше аналогичен этому выражению с if/else
if (isset($_POST['action'])) {
    $action = $_POST['action'];
} else {
    $action = 'default';
}
Выражение (expr1) ?? (expr2) вычисляется так: expr2, если expr1 равно null, иначе expr1.

Этот оператор не вызывает предупреждения или ошибки, если левый операнд не существует, точно как языковая конструкция isset(). Это очень полезно для ключей массива.

Замечание: Обратите внимание, оператор объединения с NULL — это выражение, и он оценивается не как переменная, а как результат вычисления выражения. Это важно, если нужно вернуть значение по ссылке. Выражение return $foo ?? $bar; в функции, возвращающей ссылку, будет не работать, а выводить предупреждение.

Замечание:

У оператора объединения с NULL низкий приоритет. То есть при смешивании его с другими операторами (например, с операторами конкатенации строк или арифметическими операторами), скорее всего, потребуются круглые скобки.

<?php

// Вызывает предупреждение о том, что переменную $name не определили
print 'Mr. ' . $name ?? 'Anonymous';

// Выведет "Mr. Anonymous"
print 'Mr. ' . ($name ?? 'Anonymous');

?>

Замечание:

Обратите внимание, оператор объединения с NULL разрешает простую вложенность:

Пример #8 Вложенный оператор null coalescing

<?php

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

echo $foo ?? $bar ?? $baz ?? $qux; // Выведет 1

?>

To Top