Avatar ·

Чем отличаются операторы сравнения == (нестрогое равенство) и === (строгое равенство) в PHP?

Всем привет! Я только начал изучать PHP и столкнулся с непонятной ситуацией. Пишу простой скрипт для проверки возраста пользователя, и результаты меня смущают.

Вот мой код:

<?php
$age = "25";  // строка
$legal_age = 25;  // число

if ($age == $legal_age) {
    echo "Возраст совпадает (==)";  // это выводится
}

if ($age === $legal_age) {
    echo "Возраст совпадает (===)";  // это НЕ выводится
}
?>

Почему первый if срабатывает, а второй нет? Вроде бы и там, и там значения одинаковые — 25. Я читал в мануале, что есть == и ===, но разница для меня неочевидна. Когда какой оператор использовать? И что будет, если я случайно перепутаю их в реальном проекте? Например, при проверке пароля или ID из базы данных?

Заранее спасибо за разъяснения!

<<>>

Подробное объяснение разницы между == и === в PHP

Отличный вопрос! Это одна из самых частых "ловушек" для новичков в PHP. Давайте разберёмся по порядку.

В PHP есть два основных оператора сравнения:

  • == (нестрогое равенство / equality) — сравнивает значения после приведения типов.
  • === (строгое равенство / identity) — сравнивает значения без приведения типов (проверяет и значение, и тип данных).

В вашем примере:

$age = "25";   // string
$legal_age = 25; // integer

Оператор == сначала преобразует строку "25" в число 25, а потом сравнивает. Поэтому "25" == 25 — это true.

Оператор === сразу видит, что тип данных разный (string vs integer), и возвращает false, даже не глядя на значение.

Когда какой оператор использовать?

  • Всегда используйте ===, если это возможно. Это предотвращает неожиданные ошибки, связанные с автоматическим преобразованием типов. Особенно это важно при проверке:
    • Паролей и хэшей (например, password_verify() внутри использует строгое сравнение).
    • ID записей из базы данных (они могут приходить как строки, даже если вы храните числа).
    • Результатов функций, которые могут вернуть 0, false, null или пустую строку — их легко перепутать с ==.
  • Используйте == только тогда, когда вы осознанно хотите сравнить значения с приведением типов. Например, при получении данных из формы (всегда строки) и сравнении с числовыми константами.

Коварные примеры с ==

Вот несколько ситуаций, где == ведёт себя неочевидно:

var_dump(0 == "abc");      // true! (строка "abc" преобразуется в 0)
var_dump("0" == false);    // true (false преобразуется в 0)
var_dump(null == "");      // true (оба преобразуются в пустое значение)
var_dump(false == array());// true (оба считаются "пустыми")
var_dump("123abc" == 123); // true (строка преобразуется в 123, часть "abc" отбрасывается)

Сравните с ===:

var_dump(0 === "abc");      // false
var_dump("0" === false);    // false
var_dump(null === "");      // false
var_dump(false === array());// false
var_dump("123abc" === 123); // false

Практический совет для начинающих

Возьмите за правило: никогда не используйте == для сравнения, если вы не уверены на 100%, что это безопасно. В 95% случаев вам нужен ===. Многие современные PHP-стандарты (PSR) и статические анализаторы (PHPStan, Psalm) настоятельно рекомендуют именно строгое сравнение.

Особенно будьте осторожны с функциями вроде strpos():

$pos = strpos("hello world", "hello");
if ($pos == false) { // ОШИБКА! strpos вернул 0, а 0 == false — это true!
    echo "Строка не найдена";
}
// Правильно:
if ($pos === false) {
    echo "Строка не найдена";
}

В итоге: == — это "снисходительное" сравнение, которое пытается угадать, что вы имели в виду. === — это строгая проверка, которая не делает предположений. Используйте строгое сравнение по умолчанию — и ваша жизнь станет проще.

<<>>

Дополнение: оператор spaceship (<=>) и приведение типов

Коллега выше отлично объяснил базу. Хочу добавить пару важных моментов для тех, кто уже немного освоился.

В PHP 7 появился оператор spaceship <=>, который возвращает -1, 0 или 1. Он тоже использует нестрогое сравнение (как ==), но с одним отличием: он сравнивает строки как строки, а числа как числа, не смешивая типы агрессивно. Пример:

echo 0 <=> "abc";  // 0 (потому что строка преобразуется в 0)
echo "abc" <=> "def"; // -1 (строковое сравнение)
echo 5 <=> "5";    // 0 (строка преобразуется в число)

Также стоит знать о таблице сравнения типов в PHP. Например, null == "0" даёт false, а null == "" — true. Это может привести к багам, если вы проверяете, пришло ли значение из формы. Лучше использовать is_null() или === null.

И последний совет: если вам нужно сравнить два числа, но они могут быть в разных форматах (строка vs int), всегда приводите их к одному типу явно: (int)$value или (float)$value. Это делает код понятнее и безопаснее.