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


258

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

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

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

Ответы:


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'
?>

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

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


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иначе.


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;

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.