Сравнение: == и ===
Программе постоянно нужно сравнивать: совпал ли пароль, хватает ли денег, больше ли одно число другого. Результат сравнения — значение типа bool, true или false, и печатают его через var_dump.
Представьте кассу, где работают два кассира. Снисходительный примет строку '5' за число 5, лишь бы сумма сошлась. Строгий проверит ещё и вид: число — это число, а строка — это строка, даже если в ней та же пятёрка.
В PHP снисходительного кассира зовут ==, а строгого — ===:
<?php
var_dump(5 == '5'); // bool(true)
var_dump(5 === '5'); // bool(false)
var_dump(5 === 5); // bool(true)Разберём по строкам:
5 == '5'даётtrue:==превращает строку'5'в число и сравнивает две пятёрки.5 === '5'даётfalse: слеваint, справаstring, и на этом===заканчивает проверку.5 === 5даётtrue: совпали и тип, и значение.
Нестрогое сравнение ==
Нестрогое сравнение == сначала приводит оба значения к общему типу, а потом сравнивает их. Его пара != отвечает на обратный вопрос: 5 != '5' даёт false, потому что после приведения значения равны.
Операторы <, >, <= и >= сравнивают по тем же нестрогим правилам: '10' > 9 даёт true.
Строгое сравнение ===
Строгое сравнение === ничего не приводит. Оно истинно, только когда совпадают и тип, и значение:
5 === 5.0даётfalse:intиfloat— разные типы;5 == 5.0даётtrue: после приведения это одно и то же число;!==отвечает на обратный вопрос:5 !== '5'даётtrue.
Правило PHP 8 для чисел и строк
Самое коварное в == — сравнение числа со строкой. Здесь важно, числовая ли строка. Числовая строка — это строка, в которой записано только число: '42', '01', '4.2', '1e3'.
С PHP 8 правила такие:
- Число и числовая строка сравниваются как числа:
1 == '01'даётtrue. - Число и нечисловая строка сравниваются как строки:
0 == 'a'превращается в'0' == 'a'и даётfalse. - Две числовые строки тоже сравниваются как числа, хотя обе записаны в кавычках.
Давайте посмотрим на эти правила в коде:
var_dump(0 == 'a'); // bool(false)
var_dump('1' == '01'); // bool(true)
var_dump('10' < '9'); // bool(false)
var_dump('abc' < 'b'); // bool(true)
var_dump(null == false); // bool(true)Что здесь происходит:
'1' == '01'— обе строки числовые, и PHP сравнивает1с1;'10' < '9'даётfalse: как числа,10не меньше9, хотя по алфавиту'1'стоит раньше'9';'abc' < 'b'— нечисловые строки сравниваются по буквам, как слова в словаре;null == falseдаётtrue: при сравнении сboolзначениеnullпревращается вfalse.
До PHP 8 выражение 0 == 'a' было истинным: строку без цифр PHP превращал в 0. Этот вопрос часто задают на собеседовании: «Что изменилось в сравнении числа со строкой в PHP 8?» Ответ:
- число и нечисловая строка теперь сравниваются как строки, поэтому
0 == 'a'ложно; - две числовые строки по-прежнему сравниваются как числа, поэтому
'1' == '01'истинно; - PHP 8 не сделал
==строгим: строгое сравнение даёт только===.
Здесь картинка с кассиром нуждается в оговорке. Снисходительность == — не доброта, а жёсткий свод правил: живой кассир может передумать, а == всегда поступает так, как записано выше.
Сравнивайте через === по умолчанию. Оператор == оставьте для случаев, когда вы сознательно считаете 1 и '1' одним значением.
Оператор <=>
Оператор <=> сравнивает два значения и отвечает числом:
-1, если левое меньше:1 <=> 2;0, если они равны:2 <=> 2;1, если левое больше:3 <=> 2.
Он сравнивает по тем же нестрогим правилам, поэтому '10' <=> '9' даёт 1. За форму значка его называют «космическим кораблём».
Частая ошибка
ПИН-код из формы проверяют через ==:
$pin = '0123';
$ok = $pin == '123'; // ✗
var_dump($ok); // bool(true)Обе строки числовые, и == сравнивает их как числа 123 и 123. Неверный ПИН-код подошёл, а PHP ничего не сообщил. С === строки сравниваются как есть: $pin === '123' даёт bool(false).
Главное
==приводит типы перед сравнением, а===требует совпадения и типа, и значения.- С PHP 8 число и нечисловая строка сравниваются как строки:
0 == 'a'ложно. - Две числовые строки
==сравнивает как числа:'1' == '01'истинно, а'10' < '9'ложно. - По умолчанию сравнивайте через
===;<=>возвращает-1,0или1.