Условия и сравнение: == vs ===

Условия - это то, что спасает твой код от жизни «на авось». И да, сегодня мы разберём легендарную битву: == против ===.

if / else

<?php
$age = 17;

if ($age >= 18) {
    echo 'Проходи';
} else {
    echo 'Приходи через год';
}

elseif (цепочка условий)

<?php
$score = 83;

if ($score >= 90) {
    echo 'A';
} elseif ($score >= 75) {
    echo 'B';
} elseif ($score >= 60) {
    echo 'C';
} else {
    echo 'F';
}
В PHP `elseif` (слитно) и `else if` (раздельно) работают одинаково в фигурных скобках. Но в альтернативном синтаксисе (`if: ... elseif: ... endif;`) работает только слитное написание. Привыкай писать `elseif`.

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

Примеры, которые ломают судьбы новичков:

<?php
var_dump('0' == 0);     // true - строка "0" приводится к числу
var_dump('0' === 0);    // false - строка и число - разные типы

var_dump('' == false);  // true - пустая строка «как будто false»
var_dump('' === false); // false - строка и bool - разные типы

var_dump(0 == null);    // true - 0 «как будто null»
var_dump(0 === null);   // false - число и null - разные типы
В 99% случаев используй `===` и `!==`. Иначе однажды строка "0" внезапно станет «как будто ноль», и ты будешь искать баг полдня.

Тернарный оператор

Короткая запись if/else для присваивания:

<?php
$age = 20;
$status = ($age >= 18) ? 'взрослый' : 'ребёнок';
echo $status; // "взрослый"

// Удобно для вывода:
echo 'Роль: ' . ($isAdmin ? 'Администратор' : 'Пользователь');
`$a ? $b : $c ? $d : $e` - нечитаемо и ведёт себя неочевидно. Если нужно больше одного условия - используй `if/elseif`.

Оператор ?? (null coalescing)

Возвращает первое «не null» значение:

<?php
$name = $_GET['name'] ?? 'Гость';
// Если $_GET['name'] не существует или null → 'Гость'

// Цепочка:
$config = $customConfig ?? $envConfig ?? $defaultConfig;

Оператор ??= (PHP 7.4+) - присвоить, если null:

<?php
$user['role'] ??= 'viewer'; // если role не задан → ставим 'viewer'

Логические операторы

<?php
$isLoggedIn = true;
$isAdmin = false;

// && (И) - оба должны быть true
if ($isLoggedIn && $isAdmin) {
    echo 'Админ-панель';
}

// || (ИЛИ) - хотя бы одно true
if ($isLoggedIn || $isAdmin) {
    echo 'Есть доступ';
}

// ! (НЕ) - инвертирует
if (!$isAdmin) {
    echo 'Ты не админ';
}

Ленивое вычисление (short-circuit): если первая часть && - false, вторая не проверяется. Это полезно:

<?php
// Безопасно: если $user null, ->isActive() не вызовется
if ($user !== null && $user->isActive()) {
    echo 'Активный пользователь';
}

switch

<?php
$role = 'editor';

switch ($role) {
    case 'admin':
        echo 'Полный доступ';
        break;
    case 'editor':
        echo 'Можно редактировать';
        break;
    default:
        echo 'Только читать';
}
Без `break` выполнение «проваливается» (fall-through) в следующий case. Иногда это нужно намеренно, но чаще - это баг.

match (PHP 8+)

Современная замена switch - без fall-through и со строгим сравнением:

<?php
$role = 'editor';

$access = match ($role) {
    'admin'  => 'Полный доступ',
    'editor' => 'Можно редактировать',
    default  => 'Только читать',
};

echo $access;

Отличия от switch: match использует === (строгое сравнение), возвращает значение, не нужен break, и выбрасывает UnhandledMatchError, если ни один case не подошёл и нет default.

<?php
// Несколько значений в одном case:
$httpCode = 404;

$message = match ($httpCode) {
    200, 201     => 'OK',
    301, 302     => 'Redirect',
    404          => 'Not Found',
    500, 502     => 'Server Error',
    default      => 'Unknown',
};

Spaceship-оператор <=>

Возвращает -1, 0 или 1 - удобен для сортировки:

<?php
echo 1 <=> 2;  // -1 (первый меньше)
echo 2 <=> 2;  //  0 (равны)
echo 3 <=> 2;  //  1 (первый больше)

// В usort:
$users = [['age' => 25], ['age' => 18], ['age' => 30]];
usort($users, fn($a, $b) => $a['age'] <=> $b['age']);

Приведение типов в условиях

PHP приводит значения к bool в условиях. Что считается false:

<?php
// Все эти значения - falsy (приводятся к false):
if (false) {}   // false
if (0) {}       // ноль
if (0.0) {}     // ноль с плавающей точкой
if ('') {}      // пустая строка
if ('0') {}     // строка "0" - сюрприз!
if ([]) {}      // пустой массив
if (null) {}    // null
`if ("0")` - false. Это одна из самых неочевидных особенностей PHP. Если проверяешь строку на «не пустая», используй `$str !== ''` вместо `if ($str)`.

Типичные ошибки

  • Ловушки == с приведением типов. "0abc" == 0true (старая версия PHP до 8.0 кастит строку в число), "" == nulltrue, 0 == "any string" в PHP 7 тоже true. Сравнивай через === и !== - это единственный способ не наступить на грабли.
  • Висящий fall-through в switch. Забыл break - выполнение «провалилось» в следующий case и сделало то, чего ты не ждал. Если fall-through нужен намеренно - оставь комментарий // fallthrough, чтобы ревьюер понял.
  • Отсутствие default в switch / match. В switch без default неподходящий ввод тихо игнорируется и баг всплывёт через неделю. В match будет UnhandledMatchError - лучше явно бросить исключение, чем молча проглотить.
  • Путаница switch vs match. switch использует == (нестрогое), match - === (строгое) и возвращает значение. Не путай: match (1) { "1" => ... } не сработает, а switch (1) { case "1": ... } - сработает. Для новой логики бери match.
  • Неявная истинность строк. if ("0") - false, if ("0.0") - true, if ("false") - true. Если проверяешь «строка не пуста», пиши $str !== '', а не if ($str).

Best practices

  • Используй === и !== по умолчанию; == оставь только когда осознанно нужен juggling.

  • Предпочитай match вместо switch в новом коде - строгое сравнение, возврат значения, нет fall-through.

  • Всегда добавляй default (или явный throw new \UnexpectedValueException(...)) в switch / match, чтобы неожиданный ввод не молчал.

  • Для проверки «значение есть» пиши конкретно: $x !== null, $str !== '', count($arr) > 0 - а не полагайся на truthy-приведение.

  • Не вкладывай тернарники и не комбинируй ?? с ?: без скобок - читаемость падает быстрее, чем кажется.

  • Python - Условные конструкции: if, elif, walrus (:=) - те же паттерны в Python: тернарный, match-case (Python 3.10+)

Мини-задание

  • Напиши проверку логина: если $user !== null - «Привет», иначе - «Войди»
  • Проверь разницу == и === на примерах: "10" и 10, "" и 0, null и false
  • Перепиши цепочку if/elseif через match (PHP 8+)
  • Используй ?? для безопасного чтения $_GET['page'] с дефолтом
  • Напиши usort с оператором <=> для сортировки массива пользователей по возрасту

Зарегистрируйтесь бесплатно, чтобы пройти квиз, решить задание с автопроверкой и вести прогресс.