Avatar ·

Что делает оператор ?: (Элвис) в PHP и как он работает?

Всем привет! Я начал изучать PHP недавно, и наткнулся на странный оператор `?:`. В одном проекте увидел такой код: ```php $name = $_GET['name'] ?: 'гость'; ``` Я понимаю обычный тернарный оператор `? :`, но тут стоит только один знак вопроса и двоеточие. Никакого условия до `?` нет. Как это работает? Что такое "оператор Элвиса"? Я попробовал поиграться с ним локально: ```php $value = 0; $result = $value ?: 'значение по умолчанию'; echo $result; // выводит 'значение по умолчанию' ``` Почему для `0` сработало как false? И что будет, если переменная не определена? Выдаст ли это ошибку? Объясните, пожалуйста, для новичка: в каких случаях лучше использовать `?:` вместо обычного тернарного оператора или `??` (null coalescing)? Когда стоит его применять, а когда лучше избегать? Заранее спасибо! <<>>

Что такое оператор Элвиса (?:)

Оператор ?: (Elvis operator) — это сокращённая форма тернарного оператора. Он появился в PHP 5.3. Название происходит от смайлика с причёской Элвиса Пресли: ?: похож на глаза и чёлку.

Синтаксис:

$result = $expression ?: $default;

Это эквивалентно:

$result = $expression ? $expression : $default;

Как он работает

Оператор проверяет левый операнд в логическом контексте (как boolean). Если он истинный (truthy), то возвращается его значение. Если ложный (falsy) — возвращается правый операнд.

В PHP falsy-значениями считаются:

  • false
  • 0 и 0.0 (целый ноль и дробный)
  • '' и '0' (пустая строка и строка "0")
  • [] (пустой массив)
  • null

Примеры:

echo 42 ?: 'default';   // 42
echo 0 ?: 'default';     // 'default'
echo 'hello' ?: 'default'; // 'hello'
echo '' ?: 'default';     // 'default'
echo null ?: 'default';   // 'default'

Важное отличие от ?? (null coalescing)

Оператор ?? (PHP 7+) проверяет только на null и на существование переменной (isset). А ?: проверяет на любое falsy-значение.

$x = 0;
echo $x ?: 100;  // 100 (0 — falsy)
echo $x ?? 100;  // 0 (0 не null, переменная существует)

$y = null;
echo $y ?: 100;  // 100 (null — falsy)
echo $y ?? 100;  // 100 (null)

Проблема с неопределёнными переменными

Если переменная слева от ?: не определена, PHP выдаст Notice: Undefined variable. В этом случае ?? безопаснее — он не вызывает ошибку.

// $z не определена
echo $z ?: 'default';  // Notice: Undefined variable + 'default'
echo $z ?? 'default';  // 'default' (без notice)

Когда использовать

Рекомендуется:

  • Когда вы уверены, что переменная определена, и хотите заменить все falsy-значения (включая 0, пустую строку) на дефолт
  • Для коротких цепочек проверки, например: $result = $data['count'] ?: 0;
  • В комбинации с функциями, возвращающими значение или false

Не рекомендуется:

  • Если 0 или пустая строка — допустимые значения (они будут заменены)
  • С неопределёнными переменными — используйте ??
  • В сложных выражениях — читаемость страдает

Практический пример

function getUserName($id) {
    $name = fetchFromDatabase($id);
    // Если имя пустое, null или false — показываем 'Аноним'
    return $name ?: 'Аноним';
}

// Лучше с ?? если возможен null от БД:
return $name ?? 'Аноним'; // но тогда 0 и '' останутся

Итог: оператор Элвиса — удобная синтаксическая "соль", но требует понимания falsy-значений. Для новичков чаще безопаснее использовать ?? или полный тернарный оператор с явным условием.

<<>>

Альтернативный взгляд: используйте полный тернарный оператор для ясности

Хотя оператор Элвиса выглядит компактно, он может вводить в заблуждение. Многие разработчики (особенно в командах) предпочитают явный тернарный оператор для лучшей читаемости:

// Вместо:
$greeting = $user->name ?: 'Гость';

// Лучше написать:
$greeting = $user->name ? $user->name : 'Гость';

// Или ещё более явно:
$greeting = !empty($user->name) ? $user->name : 'Гость';

Почему это важно? ?: не проверяет существование ключа в массиве или свойства объекта. Если $user->name не существует — будет ошибка. А empty() безопасно проверяет и существование, и falsy-значения.

Также помните: если вам нужно проверить только на null/неопределённость — используйте ??. Если нужно проверить на пустоту (включая 0 и '') — используйте empty() или явное условие. Оператор Элвиса — это "золотая середина", но не всегда уместная.

Мой совет для начинающих: сначала пишите полный тернарный оператор. Когда поймёте все нюансы falsy-значений, можно переходить на ?: для простых случаев.