Elvis vs Null Coalescing: секретное оружие PHP-разработчика

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Elvis vs Null Coalescing: в чём подвох? (Разбор под капотом PHP)

Привет, коллега! Если ты хоть раз писал на PHP, то наверняка сталкивался с ситуацией, когда нужно проверить, существует ли переменная, и если да — использовать её значение, а если нет — подставить что-то по умолчанию. Вроде бы простая задача, но именно здесь новички (и не только) часто спотыкаются о два очень похожих, но принципиально разных оператора: short-ternary (Elvis operator) ?: и null coalescing operator ??.

Это один из самых популярных вопросов на Stack Overflow (тысячи просмотров и голосов). И не зря: разница между ними — не просто академический интерес. Ошибка в выборе оператора может привести к багам, которые вы будете отлавливать часами. Давай раз и навсегда разберёмся, что у них «под капотом» и когда что использовать.

Короткое введение: зачем нам вообще эти операторы?

Представь, что ты пишешь код для отображения имени пользователя. Если имени нет — показываем «Гость». Классический способ — if:

if (isset($userName)) {
    $displayName = $userName;
} else {
    $displayName = 'Гость';
}

Работает, но громоздко. PHP предлагает элегантные сокращения. И тут мы подходим к главной дилемме: ?: или ??? На первый взгляд — одно и то же. Но это только на первый взгляд.

1. Elvis operator (?:) — «Король булевых значений»

Оператор Elvis (прозванный так за сходство с причёской короля рок-н-ролла: ?: — глаза, нос и чёлка) появился в PHP ещё в версии 5.3. Это сокращённая форма тернарного оператора.

Синтаксис:

$result = $expression ?: $default;

Что это значит? Интерпретатор смотрит на $expression. Если он преобразуется в true (то есть не является «ложным» значением), то возвращается $expression. Если $expression — «ложное» (false, 0, пустая строка, null, пустой массив и т.д.), то возвращается $default.

Важный нюанс: Elvis operator не проверяет, существует ли переменная. Он проверяет её истинность. Если переменная не определена, вы получите Notice: Undefined index/variable.

Пример с подвохом:

$count = 0;
$result = $count ?: 10;
echo $result; // Выведет 10, а не 0!

Почему? Потому что 0 — это «ложное» значение (falsy). Elvis посчитал, что переменная «пустая», и отдал запасной вариант. Для многих это становится сюрпризом.

2. Null Coalescing Operator (??) — «Спаситель от Notice»

Оператор null coalescing появился в PHP 7.0 и был встречен с восторгом. Его главная суперсила — он безопасно работает с несуществующими переменными, не вызывая ошибок.

Синтаксис:

$result = $expression ?? $default;

Что это значит? Оператор проверяет, существует ли $expression и не равен ли он null. Если да — возвращает $expression. В противном случае — $default.

Ключевое отличие: ?? игнорирует все «ложные» значения, кроме null и неопределённости (undefined). 0, "", false — всё это считается валидными значениями и будет возвращено.

Пример:

$count = 0;
$result = $count ?? 10;
echo $result; // Выведет 0! Потому что переменная существует и не null.

Видишь разницу? Это и есть главный «подкапотный» механизм.

3. Сравнение «под капотом»: таблица истинности

Давай сведём всё в наглядную таблицу, чтобы закрепить. Пусть у нас есть переменная $x с разными значениями.

Значение $x $x ?: 'default' $x ?? 'default'
Не определенаNotice + 'default''default' (без Notice)
null'default' (null — falsy)'default'
false'default'false
0'default'0
'' (пустая строка)'default'''
'Hello''Hello''Hello'

Вывод из таблицы: ?? — это оператор «существует и не null». ?: — это оператор «является истинным». Они решают разные задачи, хотя внешне похожи.

4. Цепочки вызовов: где магия становится очевидной

Оба оператора поддерживают chaining (цепочки). Но ведут они себя по-разному.

Цепочка с ?? (Null Coalescing):

$name = $_GET['name'] ?? $_POST['name'] ?? 'Гость';

Это работает как «найди первое существующее и не null значение». Идеально для форм.

Цепочка с ?: (Elvis):

$name = $_GET['name'] ?: $_POST['name'] ?: 'Гость';

Это будет работать только если переменные определены (иначе Notice). И вернёт первое «истинное» значение. Если имя пользователя — пустая строка, цепочка пойдёт дальше.

На практике цепочки с ?? встречаются гораздо чаще, так как они безопаснее.

5. Практический пример из жизни: настройки и конфиги

Представь, что ты читаешь настройки приложения из массива. Ключ может отсутствовать, а значение может быть 0 или false (например, флаг «отключить кеш»).

$config = [
    'cache_enabled' => false, // Кеш выключен                

Блоги

Рекомендаций по книгам