Quem é Elvis e o que ele tem a ver com PHP?
\n\nSe você já escreveu em PHP, provavelmente já viu construções estranhas no código de outras pessoas: $name ?: 'Convidado' ou $name ?? 'Convidado'. À primeira vista, parecem a mesma coisa. Mas, na verdade, por trás desses dois operadores, existem mecânicas completamente diferentes que podem tanto salvar seu código quanto causar problemas.
No Stack Overflow, a pergunta "PHP short-ternary ("Elvis") operator vs null coalescing operator" acumulou dezenas de milhares de visualizações. E não é por acaso. Desenvolvedores se confundem, cometem erros e depois passam muito tempo procurando bugs. Vamos entender de uma vez por todas quem é quem e parar de adivinhar.
\n\nNeste artigo, não vamos apenas listar as diferenças. Vamos olhar sob o capô do PHP, analisar casos reais de produção e entender quando usar cada operador. Vamos nessa!
\n\nBreve introdução: o que são esses operadores?
\n\nOperador ternário (clássico)
\nPrimeiro, vamos relembrar o básico. O operador ternário é uma forma abreviada de if-else:
\n\n$age = 20;\n$status = ($age >= 18) ? 'Adulto' : 'Criança';\n// $status = 'Adulto'\n\nSimples: se a condição for verdadeira, pegamos o primeiro valor; caso contrário, o segundo.
\n\nShort-ternary (também conhecido como operador Elvis) — ?:
\nÉ uma abreviação para quando você verifica se uma variável é "verdadeira" e quer usar o próprio valor dela:
\n\n$name = 'Alex';\n$greeting = $name ?: 'Convidado';\n// $greeting = 'Alex'\n\n$name = '';\n$greeting = $name ?: 'Convidado';\n// $greeting = 'Convidado'\n\nFunciona assim: se $name for convertido para true, usamos $name. Caso contrário, usamos "Convidado".
Operador null coalescing — ??
\nSurgiu no PHP 7.0 e rapidamente se tornou o favorito dos desenvolvedores:
\n\n$name = 'Alex';\n$greeting = $name ?? 'Convidado';\n// $greeting = 'Alex'\n\n$name = null;\n$greeting = $name ?? 'Convidado';\n// $greeting = 'Convidado'\n\nA diferença do Elvis: a verificação é apenas para null, e não para "falsidade" em geral.
\n\nDiferença principal: o que é considerado "vazio"?
\n\nAqui é onde a coisa fica interessante. Vamos ver uma tabela de comparação para diferentes valores de $value:
$value = false;\necho $value ?: 'default'; // 'default' (false é "falso")\necho $value ?? 'default'; // false (false NÃO é null)\n\n$value = 0;\necho $value ?: 'default'; // 'default' (0 é "falso")\necho $value ?? 'default'; // 0 (0 NÃO é null)\n\n$value = '';\necho $value ?: 'default'; // 'default' (string vazia é "falso")\necho $value ?? 'default'; // '' (string vazia NÃO é null)\n\n$value = [];\necho $value ?: 'default'; // 'default' (array vazio é "falso")\necho $value ?? 'default'; // [] (array vazio NÃO é null)\n\n$value = '0';\necho $value ?: 'default'; // 'default' (string "0" é "falso"!)\necho $value ?? 'default'; // '0' (string "0" NÃO é null)\n\nViu a diferença? O Elvis funciona como uma verificação de "veracidade" (truthy/falsy), enquanto o null coalescing é uma verificação estrita de existência e diferença de null.
\n\nSob o capô: como funciona no nível do motor
\n\nVamos dar uma olhada nos fontes do PHP (bem, quase). Se você já compilou o PHP a partir do código fonte, sabe que ambos os operadores são processados na fase de parsing.
\n\nShort-ternary (?):
\nNa prática, é um açúcar sintático. $a ?: $b se transforma em $a ? $a : $b. Mas há um detalhe: o PHP não calcula $a duas vezes. Ele salva o resultado em uma variável temporária. Isso é importante para funções com efeitos colaterais:
function getData() {\n echo "Função chamada!\\n";\n return rand(0, 1) ? 'data' : '';\n}\n\n// Elvis chama a função UMA vez\n$result = getData() ?: 'default';\n// "Função chamada!" — uma vez\n\nSe o PHP calculasse $a duas vezes,