Перейти к содержимому
Теория · Операторы и сравнение · урок 4 из 8

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

Программе постоянно нужно сравнивать: совпал ли пароль, хватает ли денег, больше ли одно число другого. Результат сравнения — значение типа bool, true или false, и печатают его через var_dump.

Представьте кассу, где работают два кассира. Снисходительный примет строку '5' за число 5, лишь бы сумма сошлась. Строгий проверит ещё и вид: число — это число, а строка — это строка, даже если в ней та же пятёрка.

В PHP снисходительного кассира зовут ==, а строгого — ===:

PHP
<?php

var_dump(5 == '5'); // bool(true)
var_dump(5 === '5'); // bool(false)
var_dump(5 === 5); // bool(true)

Разберём по строкам:

  1. 5 == '5' даёт true: == превращает строку '5' в число и сравнивает две пятёрки.
  2. 5 === '5' даёт false: слева int, справа string, и на этом === заканчивает проверку.
  3. 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. Число и числовая строка сравниваются как числа: 1 == '01' даёт true.
  2. Число и нечисловая строка сравниваются как строки: 0 == 'a' превращается в '0' == 'a' и даёт false.
  3. Две числовые строки тоже сравниваются как числа, хотя обе записаны в кавычках.

Давайте посмотрим на эти правила в коде:

PHP
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. За форму значка его называют «космическим кораблём».

Частая ошибка

ПИН-код из формы проверяют через ==:

PHP
$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.