Оператор == порівнює значення з приведенням типів, === порівнює і значення, і тип без жодних перетворень.
Оператор == порівнює значення після приведення до спільного типу, === порівнює значення і тип без перетворень. Через це === завжди передбачуваний: '1' === 1 ніколи не стане true, бо це рядок і ціле число.
У PHP 8 правила приведення для == стали строгішими. Число порівнюється з рядком як число лише тоді, коли рядок числовий ('42', ' 1.5'). Нечисловий рядок більше не перетворюється на 0: замість цього число приводиться до рядка, і порівняння йде посимвольно. Саме тому 0 == 'abc' у PHP 8 повертає false, а в PHP 7 повертало true.
Нестроге порівняння живе не лише в операторі. in_array, array_search, array_keys з другим аргументом і switch за замовчуванням використовують ==. Тому в них потрібно передавати true третім аргументом або замінити switch на match, який порівнює строго.
Окремий випадок: float. === порівнює біти, тому 0.1 + 0.2 === 0.3 дає false через похибку представлення. Тут не допомагає жоден оператор, потрібен допуск або тип без плаваючої точки.
var_dump(0 == 'abc'); // PHP 8: false, PHP 7: true
var_dump('1' == '01'); // true: обидва числові рядки
var_dump('1' === '01'); // false: різні рядки
var_dump(null == false); // true
var_dump(null === false); // false: різні типи
// Та сама пастка всередині in_array
var_dump(in_array('1e1', ['10'])); // true: '1e1' == '10' як числа
var_dump(in_array('1e1', ['10'], true)); // false: строгий режим
// switch порівнює нестрого: '0' == false дає true, тому спрацює перша гілка
switch ('0') {
case false: echo 'false'; break;
case '0': echo 'zero'; break;
}
// match порівнює строго
echo match ('0') { false => 'false', '0' => 'zero' }; // zero
Скажіть, що в продакшн-коді за замовчуванням використовуєте === і declare(strict_types=1), а == лишаєте для випадків, де приведення справді потрібне, і наведіть один такий випадок.