Применение ?: в коде 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.