Глиф Учебники

Разница между == и ===

Справочник · PHP · 2 минуты чтения

То же с отрицаниями: != (не равно) и !== (не тождественно).

PHP
<?php
var_dump(5 == "5");
var_dump(5 === "5");
var_dump(0 == "");
var_dump(null == false);
var_dump("1" == "01");
var_dump("abc" == 0);
var_dump(1.0 === 1);
Вывод
bool(true)
bool(false)
bool(false)
bool(true)
bool(true)
bool(false)
bool(false)

Что изменилось в PHP 8

Раньше число сравнивалось со строкой так: строка превращалась в число, а строка без цифр давала 0. Поэтому в PHP 7 0 == "abc" и 0 == "" были истинны. В PHP 8 правило другое: если строка не похожа на число, уже число превращается в строку, и 0 == "abc" — это "0" == "abc", то есть false. Старый код, который полагался на прежнее поведение, после перехода на PHP 8 может работать иначе.

Где == подводит

strpos. Функция возвращает позицию найденного текста, а позиция в начале строки — 0:

PHP
<?php
$pos = strpos("php уроки", "php");
if ($pos == false) {
    echo "не найдено\n";
}
if ($pos !== false) {
    echo "найдено на позиции $pos\n";
}
Вывод
не найдено
найдено на позиции 0

0 == false истинно, поэтому первая проверка ошиблась. Правильно — !== false, а в PHP 8 проще всего str_contains("php уроки", "php").

in_array и array_search по умолчанию сравнивают через ==. Третий аргумент true включает строгое сравнение: in_array("1", [1, 2, 3], true) вернёт false, потому что в массиве числа, а не строки.

switch сравнивает через ==, а match — через ===. Если важен тип, берите match.

Пароли и токены не сравнивают ни ==, ни ===: для паролей есть password_verify, для секретных строк — hash_equals: она тратит на сравнение одинаковое время, и по скорости ответа нельзя узнать, сколько знаков совпало.

Что выбрать

Пишите === и !== по умолчанию. Тогда сравнение делает ровно то, что написано, и неожиданных совпадений вроде "1" == "01" не бывает. Если сравниваются данные из формы (там всегда строки) с числами, сначала явно приведите тип: (int) ($_GET['page'] ?? 0) === 1.

Сравнение на «больше» и «меньше» (<, >) строгой формы не имеет и тоже приводит типы, поэтому перед ним приводите значения к числу сами.