Что означает двойной вопросительный знак (??) в PHP? Оператор объединения с null
Что такое оператор объединения с null (??)
Двойной вопросительный знак ?? в PHP — это оператор объединения с null (null coalescing operator). Он появился в PHP 7.0 и стал настоящим спасением для тех, кто устал писать громоздкие проверки с isset().
Синтаксис и логика работы
Оператор выглядит так:
$result = $expression1 ?? $expression2;
Он работает следующим образом:
- Если
$expression1существует и не равен null, то возвращается значение$expression1. - В противном случае возвращается
$expression2.
Важнейшая особенность: оператор не вызывает предупреждение (warning), если переменная или ключ массива не существует. Он ведёт себя точно так же, как isset().
Простой пример
<?php
// Вместо длинной проверки:
$username = isset($_GET['user']) ? $_GET['user'] : 'гость';
// Теперь можно писать кратко:
$username = $_GET['user'] ?? 'гость';
echo "Привет, $username!";
?>
Если в URL передан параметр ?user=Иван, выведется "Привет, Иван!". Если параметра нет — "Привет, гость!". Никаких ошибок и предупреждений.
Чем отличается от тернарного оператора?
Многие путают ?? с сокращённым тернарным оператором ?: (один вопросительный знак). Разница критическая:
<?php
// Тернарный оператор ?: проверяет на "истинность" (truthy/falsy)
$value1 = 0 ?: 'default'; // Вернёт 'default', так как 0 считается false
$value2 = '' ?: 'default'; // Вернёт 'default', пустая строка — false
// Оператор ?? проверяет ТОЛЬКО на null и несуществование
$value3 = 0 ?? 'default'; // Вернёт 0, так как 0 — это не null
$value4 = '' ?? 'default'; // Вернёт '', пустая строка — не null
?>
Это очень важно: ?? не считает пустую строку, ноль или false "пустыми" значениями. Он реагирует только на null и отсутствие переменной.
Работа с массивами и вложенными данными
Особенно удобен оператор при работе с массивами, например, с данными из форм или API:
<?php
$data = [
'name' => 'Анна',
'age' => null,
'city' => ''
];
// Обычная проверка:
$name = isset($data['name']) ? $data['name'] : 'Неизвестно';
$age = isset($data['age']) ? $data['age'] : 'Не указан';
$city = isset($data['city']) ? $data['city'] : 'Не указан';
// С оператором ??:
$name = $data['name'] ?? 'Неизвестно'; // 'Анна'
$age = $data['age'] ?? 'Не указан'; // 'Не указан' (потому что null)
$city = $data['city'] ?? 'Не указан'; // '' (пустая строка — не null!)
?>
Обратите внимание на $city: так как значение существует и не равно null, вернётся пустая строка. Если вам нужно проверить и на пустоту, используйте другие методы.
Цепочка операторов
Операторы можно объединять в цепочку для последовательной проверки нескольких значений:
<?php
// Поиск первого не-null значения
$config = $envConfig ?? $fileConfig ?? $defaultConfig ?? 'стандартные настройки';
?>
Это работает слева направо: если $envConfig не null — берём его, иначе проверяем $fileConfig и так далее.
Nullsafe-оператор (?->) — дополнение из PHP 8
В PHP 8 появился похожий оператор для цепочек вызовов методов — ?-> (nullsafe operator). Он позволяет безопасно обращаться к методам и свойствам объектов, которые могут быть null:
<?php
// Без nullsafe:
$country = null;
if ($user !== null) {
$address = $user->getAddress();
if ($address !== null) {
$country = $address->getCountry();
}
}
// С nullsafe (PHP 8+):
$country = $user?->getAddress()?->getCountry();
?>
Подводные камни
- Не путайте с ?: Оператор
??проверяет только на null/несуществование, а?:— на "ложность" (false, 0, '', null, []). - Приоритет: Оператор
??имеет низкий приоритет. Если используете его в сложных выражениях, ставьте скобки:($a ?? $b) + 5. - Не заменяет isset() для множества переменных: Если нужно проверить сразу несколько вложенных ключей,
isset()может быть удобнее.
Итог
Оператор ?? — это элегантный способ задать значение по умолчанию для переменных, которые могут быть неопределены или равны null. Он делает код короче, чище и безопаснее. Используйте его везде, где раньше писали isset($x) ? $x : $default.
Практический пример: обработка формы с множеством полей
Допустим, у вас есть форма регистрации с 10 полями. Без оператора ?? код превращается в "простыню" из isset:
<?php
// Старый способ — ужасно
$name = isset($_POST['name']) ? trim($_POST['name']) : '';
$email = isset($_POST['email']) ? trim($_POST['email']) : '';
$phone = isset($_POST['phone']) ? trim($_POST['phone']) : '';
// ... ещё 7 полей
?>
С оператором ?? это становится лаконичным:
<?php
// Новый способ — красиво
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$phone = trim($_POST['phone'] ?? '');
// ... остальные поля
?>
Альтернативный подход: функция-обёртка
Если вам нужно часто задавать значения по умолчанию и при этом проверять на пустоту (а не только на null), можно написать свою функцию:
<?php
function getParam(array $data, string $key, $default = null) {
return isset($data[$key]) && $data[$key] !== '' ? $data[$key] : $default;
}
// Использование:
$name = getParam($_POST, 'name', 'Неизвестно');
// Теперь пустая строка тоже будет заменена на значение по умолчанию
?>
Но для большинства случаев встроенный ?? — это именно то, что нужно. Он встроен в язык, работает быстро и не требует дополнительных функций.
Совет для новичков
Начните с замены всех конструкций вида isset($x) ?
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги