?: оператор («оператор Элвиса») в PHP

258

Я видел это сегодня в некотором коде PHP:

$items = $items ?: $this->_handle->result('next', $this->_result, $this);

Я не знаком с ?:оператором, используемым здесь. Это похоже на троичный оператор, но выражение для оценки, если предикат истинен, было опущено. Что это означает?

alpha_juno
источник

Ответы:

529

Он оценивает левый операнд, если левый операнд верный , а правый операнд - в противном случае.

В псевдокоде,

foo = bar ?: baz;

грубо решается на

foo = bar ? bar : baz;

или

if (bar) {
    foo = bar;
} else {
    foo = baz;
}

с той разницей, что barбудет оцениваться только один раз.

Вы также можете использовать это для «самопроверки», fooкак показано в примере кода, который вы разместили:

foo = foo ?: bar;

Это будет назначать barв fooслучае fooравна нулю или falsey, иначе он оставит fooбез изменений.

Еще несколько примеров:

<?php
    var_dump(5 ?: 0); // 5
    var_dump(false ?: 0); // 0
    var_dump(null ?: 'foo'); // 'foo'
    var_dump(true ?: 123); // true
    var_dump('rock' ?: 'roll'); // 'rock'
?>

Кстати, это называется оператор Элвиса .

Элвис оператор

BalusC
источник
11
Убедитесь, что переменная в скобках существует, или вы собираетесь выдать ошибку. PHP не просто предполагает, что он имеет значение nullили что-то еще. Просто
скажи
20
Что забавно, этот ответ образует рекурсивный цикл со статьей Wiki, которая не полностью объясняет, почему он называется «оператор Элвиса».
seeming.amusing
41
Немного меньше операции, немного больше выражения, пожалуйста.
aalaap
2
Почему бы просто не использовать ||. Так что blah || 'default'?
Noitidart
10
@Noitidart Потому что, в отличие от JS, где он возвращает самый левый истинный операнд, в PHP ||оператор всегда возвращает логическое значение.
Ксадовский
58

Смотрите документы :

Начиная с PHP 5.3, можно опустить среднюю часть троичного оператора. Выражение expr1 ?: expr3возвращается, expr1если expr1вычисляется как TRUE, и expr3иначе.

Yacoby
источник
10
Им нужен новый автор документов, потому что неизбежно кто-то спросит, что случилось с expr2. Я просто подумал.
Джон К
7
Какого черта? Я просто выяснил это сейчас, сразу после обновления до PHP 7? Я мог бы использовать это в течение многих лет!
Баттл Буткус
ТБХ, документы правильные. То, что случилось, expr2- то, что это просто исчезло, и не оценено. $this->expensiveComputation() ?: "nope"не идентичен $this->expensiveComputation() ? $this->expensiveComputation() : "nope"- expr1 вычисляется только один раз.
Писквор покинул здание
18

Будьте осторожны с массивами. Мы должны написать проверочную переменную после ?, потому что:

  $params = ['param1' => 'value1',
             'param2' => 'value2',
             'param3' => 'value3',];

  $param1 = isset($params['param1'])?:null;
  $param2 = !empty($params['param2'])?:null;
  $param3 = $params['param3']?:null; // get E_NOTICE, if $params['param3'] eq false

  var_dump($param1,$param2,$param3);
  true // would like to expect `value1`
  true // would like to expect `value2`
  param3 // properly, but problem above

обновленный

Из RFC. В будущем (в PHP 7) это сделает оператор Null Coalesce Operator , например:

$param1 = $params['param1'] ?? null;
// Equivalent to:  $param1 = isset($params['param1']) ? $params['param1'] : null;
voodoo417
источник
1
Это не отвечает на вопрос и не является полезным для тех, кто пытается понять, когда использовать оператор Элвиса.
Марк Эмери
7
@ Марк Амери Хмм .. Правда? Разве это не полезно? Вы действительно работали с PHP и рассматривали тысячи случаев использования доступа к массиву с помощью ternary? Хорошо, я изменил текст на «Будьте осторожны с массивами ..»
voodoo417
так ноль слиться и элвис одинаковы?
Набиль Хан
7
@NabeelKhan Нет! И это делает оператор Элвиса бесполезным в PHP imo. Оператор Элвиса вычисляет выражение и, если оно истинно, возвращает его, в противном случае возвращает последнюю часть. Поскольку PHP имеет низкую типизацию, многие вещи будут истинными или ложными, и, скорее всего, все будет не так, как вы хотите. Т.е.: вы хотите установить значение по умолчанию для переменной, если она не определена, используя оператор Элвиса, PHP скажет, что 0 не определено, но вы можете захотеть, чтобы 0 ... Вот почему PHP 7 получит оператор Null Coalesce , Он будет строго проверять вашу переменную с нулевым значением, поэтому PHP скажет, что 0 не является неопределенным.
Грегуар Д.
1
@FuscaSoftware: Использование такого метода подавления ошибок не очень хорошая идея по моему опыту.
TeeHays
8

Еще одно важное соображение: оператор Элвиса нарушает процесс токенизации Zend Opcache. Я нашел это трудным путем! Хотя это могло быть исправлено в более поздних версиях, я могу подтвердить, что эта проблема существует в PHP 5.5.38 (со встроенным Zend Opcache v7.0.6-dev).

Если вы обнаружите, что некоторые из ваших файлов «отказываются» кэшироваться в Zend Opcache, это может быть одной из причин ... Надеюсь, это поможет!

Прасад Парадкар
источник
4

Да, это новое в PHP 5.3. Он возвращает либо значение тестового выражения, если оно оценено как ИСТИНА, либо альтернативное значение, если оно оценено как ЛОЖЬ.

Атли
источник
2
Совершенно неправильно / вводит в заблуждение; ни один из операндов не должен быть логическим. Важно то, является ли первое значение правдивым , а не так ли TRUE.
Марк Амери
@MarkAmery уточнил. Должно быть довольно трудно неправильно истолковать это таким образом.
Atli