Применение ?: в коде PHP: от простых проверок до вложенных конструкций

Раздел: Программирование на PHP -> Основы синтаксиса PHP

Тернарный оператор: компактная замена if-else

Тернарный оператор ?: позволяет записать условное присваивание в одной строке: $result = (условие) ? значение_если_истина : значение_если_ложь.

Как заменить простую конструкцию if-else на одну строку?

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

Пояснение: условие $age >= 18 вычисляется. Если истинно, возвращается первое выражение, иначе второе. Результат присваивается $status.

Возможные проблемы

Тернарный оператор может снизить читаемость, если условие слишком сложное или выражения длинные. Рекомендуется использовать только для простых проверок.

Как реализовать несколько условий в одном выражении?

Для проверки более двух ветвей можно вложить тернарные операторы друг в друга. Следует обязательно использовать скобки, чтобы явно указать порядок вычислений.

$score = 85;
$grade = ($score >= 90) ? 'A' : (($score >= 80) ? 'B' : (($score >= 70) ? 'C' : 'D'));
echo $grade; // B

Пояснение: первое условие $score >= 90 ложно, затем проверяется второе $score >= 80 истинно, возвращается 'B'.

Типичная ошибка

Без скобок результат может отличаться в зависимости от версии PHP. До PHP 8.0 тернарный оператор был левоассоциативен, что приводило к неверному порядку вычислений. Начиная с PHP 8.0 ассоциативность изменена на правую. Рекомендуется всегда ставить скобки.

Как присвоить значение, если оно истинно, иначе заменить на другое?

Сокращенная форма $var ?: 'default' эквивалентна $var ? $var : 'default'. Используется, когда нужно оставить значение, если оно не пустое, иначе подставить запасной вариант.

$name = $_GET['name'] ?: 'Гость';
echo $name; // если параметр name передан и не пуст, выведет его, иначе 'Гость'

Пояснение: если выражение слева от ?: истинно (то есть не false, null, 0, пустая строка и т.д.), то оно и возвращается, иначе возвращается правая часть.

Ограничение

Эта форма не различает значение false и null: если $name = '' (пустая строка), то она считается false и будет заменена на 'Гость'. Если нужно различать null и пустую строку, используйте ?? (null coalescing).

Как присвоить значение по умолчанию, если переменная не определена или равна null?

Тернарный оператор с isset может проверить существование переменной, но компактнее использовать оператор ?? (null coalescing), появившийся в PHP 7.0.

$username = isset($_POST['username']) ? $_POST['username'] : 'Anonymous';
// то же самое с ??
$username = $_POST['username'] ?? 'Anonymous';

Пояснение: ?? возвращает левый операнд, если он существует и не равен null, иначе правый. Тернарный с isset требует явной проверки.

Разница с тернарным

Тернарный оператор ?: не проверяет isset, он проверяет истинность. Если переменная не определена, возникнет ошибка уровня notice. Используйте ?? для безопасного доступа к неопределенным переменным.

Как вывести одно из двух значений в зависимости от условия в составе строки?

Тернарный оператор часто применяется внутри echo или при конкатенации строк.

$isLoggedIn = true;
echo 'Пользователь ' . ($isLoggedIn ? 'авторизован' : 'не авторизован') . '.';

Пояснение: скобки вокруг тернарного оператора обязательны, иначе конкатенация будет выполнена неверно из-за приоритета операторов.

Ошибка приоритета

Без скобок выражение 'Пользователь ' . $isLoggedIn ? 'авторизован' : 'не авторизован' . '.' будет интерпретировано как ('Пользователь ' . $isLoggedIn) ? 'авторизован' : ('не авторизован' . '.'), что приведет к неожиданному результату.

Как вернуть значение на основе условия без использования if-else?

В функциях тернарный оператор позволяет компактно вернуть одно из двух значений.

function getDiscount($price) {
    return $price > 100 ? 0.1 : 0.05;
}
echo getDiscount(150); // 0.1

Пояснение: если цена больше 100, возвращается скидка 10%, иначе 5%. Это сокращает код по сравнению с if-else.

Ограничение

Для сложной логики ветвления (более двух вариантов) лучше использовать if-else или switch, чтобы сохранить читаемость.

Как динамически установить CSS класс в зависимости от значения?

При генерации HTML тернарный оператор удобен для выбора класса.

$isError = true;
echo '
Сообщение
'; // Результат: <div class="error">Сообщение</div>

Пояснение: в зависимости от булевой переменной класс меняется. Важно экранировать кавычки при выводе в HTML.

Неверный тип

Если $isError не булево (например, строка), то любая непустая строка считается true, что может быть неочевидно. Приводите значение к bool, если нужно.

Расширенные примеры использования тернарного оператора

Пример 1: Определение размера элемента на основе ширины экрана

Пример
$width = 1024;
$size = $width > 1200 ? 'large' : ($width > 768 ? 'medium' : ($width > 480 ? 'small' : 'tiny'));
echo $size; // medium
medium

Пояснение: последовательная проверка условий. Если ширина больше 1200 - large, иначе если больше 768 - medium, и т.д. Для наглядности используются скобки.

Пример 2: Форматирование числа с заданной точностью

Пример
$number = 1234.5678;
$precision = 2;
$formatted = $precision > 0 ? number_format($number, $precision) : round($number);
echo $formatted; // 1,234.57 (зависит от локали)
1,234.57

Пояснение: если точность больше нуля, используем number_format, иначе округляем до целого. number_format добавляет разделители групп тысяч.

Пример 3: Формирование конфигурации с условием

Пример
$env = 'production';
$config = [
    'debug' => $env === 'development' ? true : false,
    'cache' => $env === 'production' ? true : false,
    'log_level' => $env === 'development' ? 'debug' : 'error'
];
print_r($config);
Array
(
    [debug] => false
    [cache] => true
    [log_level] => error
)

Пояснение: значения массива зависят от окружения. Тернарный оператор позволяет компактно задать булевы флаги.

Пример 4: Вызов метода объекта в зависимости от типа

Пример
class MyClass {
    public function doSomething() { return 'MyClass result'; }
}
class OtherClass {}

$obj = new MyClass();
$result = $obj instanceof MyClass ? $obj->doSomething() : null;
echo $result; // MyClass result
MyClass result

Пояснение: проверка принадлежности объекта к классу. Если объект является экземпляром MyClass, вызывается метод, иначе возвращается null.

Пример 5: Демонстрация важности скобок при смешанных операциях

Пример
$x = 5;
$y = 3;
$result = $x > 0 ? $x : $y + 5;
echo $result; // 5 (всё верно, так как приоритет + выше ?:)
5

Пояснение: здесь $y + 5 вычисляется первым, так как сложение имеет более высокий приоритет, чем тернарный оператор. Результат: 5 (поскольку условие истинно).

Однако если написать без скобок вложенный тернарный, результат может быть неожиданным:

Пример
$a = 1; $b = 2; $c = 3;
$result = $a ? $b : $c ? $d : $e; // предупреждение об undefined $d, $e
// Правильно: $result = $a ? $b : ($c ? $d : $e);

Типичная ошибка

Из-за ассоциативности тернарного оператора (до PHP 8.0 левая) выражение $a ? $b : $c ? $d : $e интерпретируется как ($a ? $b : $c) ? $d : $e, что может привести к ошибкам. Всегда используйте скобки для вложенных тернарных.

Пример 6: Безопасное присвоение с проверкой на null и последующей проверкой значения

Пример
$data = ['count' => 0];
$result = ($data['count'] ?? null) ?: 'нет данных';
echo $result; // 'нет данных', так как 0 считается false
нет данных

Пояснение: сначала оператор ?? возвращает 0 (если ключ 'count' существует, иначе null). Затем сокращенный тернарный проверяет истинность 0 - это false, поэтому возвращается 'нет данных'. Если нужно различать 0 и null, используйте явную проверку с isset.

Тернарный оператор PHP - comments

En
тернарный оператор php (php)