?: operator (o 'operador Elvis') em PHP

258

Eu vi isso hoje em algum código PHP:

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

Não estou familiarizado com o ?:operador que está sendo usado aqui. Parece um operador ternário, mas a expressão para avaliar se o predicado é verdadeiro foi omitida. O que isso significa?

alpha_juno
fonte

Respostas:

529

Ele avalia o operando esquerdo se o operando esquerdo é verdadeiro e o operando direito, caso contrário.

No pseudocódigo,

foo = bar ?: baz;

resolve aproximadamente a

foo = bar ? bar : baz;

ou

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

com a diferença que barserá avaliada apenas uma vez.

Você também pode usar isso para fazer uma "autoavaliação", fooconforme demonstrado no exemplo de código publicado:

foo = foo ?: bar;

Isso atribuirá bara fooif fooé nulo ou falsey, caso contrário, ele foopermanecerá inalterado.

Mais alguns exemplos:

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

By the way, é chamado o operador Elvis .

Operador Elvis

BalusC
fonte
11
Certifique-se de que a variável entre parênteses exista, ou você irá gerar um erro. O PHP não assume apenas que ele possui um valor igual nullou qualquer coisa. Apenas dizendo
DanMan
20
O engraçado é que essa resposta forma um loop recursivo com o artigo da Wiki, que não explica completamente por que é chamado de "operador Elvis".
seeming.amusing
41
Um pouco menos de operação, um pouco mais de expressão, por favor.
aalaap
2
Por que não usar apenas a ||. Então blah || 'default'?
Noitidart 10/04
10
@Noitidart Como, diferentemente do JS, onde ele retorna o operando mais à esquerda, no PHP, o ||operador sempre retorna um booleano.
ksadowski
58

Veja os documentos :

Desde o PHP 5.3, é possível deixar de fora a parte do meio do operador ternário. A expressão expr1 ?: expr3retorna expr1se for expr1avaliada como TRUEou expr3não.

Yacoby
fonte
10
Eles precisam de um novo escritor de documentos, porque inevitavelmente alguém perguntará o que aconteceu com expr2. Eu apenas pensei nisso.
John K
7
Que diabos? Acabei de descobrir isso agora, logo após atualizar para o PHP 7? Eu poderia estar usando isso há anos!
Buttle Butkus
TBH, os documentos estão corretos. O que aconteceu expr2é que ele simplesmente desapareceu e não é avaliado. $this->expensiveComputation() ?: "nope"não é idêntico a $this->expensiveComputation() ? $this->expensiveComputation() : "nope"- expr1 é avaliado apenas uma vez.
Piskvor saiu do prédio 15/11/19
18

Cuidado com matrizes. Devemos escrever uma variável de verificação depois ?, porque:

  $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

Atualizada

Do RFC. No futuro (no PHP 7), o operador Null Coalesce Operator fará isso, por exemplo:

$param1 = $params['param1'] ?? null;
// Equivalent to:  $param1 = isset($params['param1']) ? $params['param1'] : null;
voodoo417
fonte
1
Isso não responde à pergunta, nem é útil para quem tenta entender quando usar o Elvis Operator.
Mark Amery
7
@ Mark Amery hmm .. Realmente? Não é útil? Você realmente trabalhou com PHP e analisou milhares de casos usando para acessar os vars da matriz com ternários? Ok, eu mudei de texto para "Tenha cuidado com matrizes .."
voodoo417
então nula coalescência e elvis são iguais?
Nabeel Khan
7
@NabeelKhan Não! E isso torna o operador Elvis meio inútil na imo do PHP. O operador Elvis avalia uma expressão e, se for verdadeira, ela a retorna, caso contrário, retorna a última parte. Como o PHP é de baixa digitação, muitas coisas serão verdadeiras ou falsas, e provavelmente as coisas não serão o que você deseja. Ou seja: você deseja definir um valor padrão para uma variável se ela não estiver definida, usando o operador Elvis, o PHP dirá que 0 não está definido, mas você pode querer que 0 ... É por isso que o PHP 7 obterá o operador Null Coalesce , Ele estritamente testará sua variável contra nulo, portanto, o PHP dirá que 0 não é indefinido.
precisa
1
@FuscaSoftware: Usar a supressão de erros como essa não é uma boa ideia na minha experiência.
TeeHays
8

Outra consideração importante: o Elvis Operator interrompe o processo de tokenização do Zend Opcache. Achei isso da maneira mais difícil! Embora isso possa ter sido corrigido em versões posteriores, posso confirmar que esse problema existe no PHP 5.5.38 (com o Zend Opcache integrado v7.0.6-dev).

Se você achar que alguns de seus arquivos 'recusam' ser armazenados em cache no Zend Opcache, esse pode ser um dos motivos ... Espero que isso ajude!

Prasad Paradkar
fonte
4

Sim, isso é novo no PHP 5.3. Retorna o valor da expressão de teste se for avaliado como TRUE ou o valor alternativo se for avaliado como FALSE.

Atli
fonte
2
Sutilmente errado / enganoso; nenhum operando precisa ser um booleano. O que importa é se o primeiro valor é verdadeiro , não se é TRUE.
Mark Amery
@MarkAmery Esclarecido. Deve ser bastante difícil interpretá-lo dessa maneira.
21315 Atli