A evolução da comparação ternária no PHP

7 years ago by Jaime Neto

O PHP vem evoluindo muito desde sua criação, principalmente nas últimas versões, que vêm incorporando os mais modernos conceitos no que diz respeito ao desenvolvimento de software. Uma das funcionalidades básicas, e que também vem trazendo evoluções, é o operador ternário. Vamos dar uma olhada nas formas que temos de utilizá-lo e entender a diferença entre elas.

Digamos que temos a seguinte comparação:

if ($a) {
    $resultado = 'a';
} else {
    $resultado = 'b';
}

Podemos fazer a mesma coisa, utilizando o operador ternário a seguir:

$resultado = $a ? 'a' : 'b';

Ok. Isso já serve pra economizar algumas linhas de código, e deixá-lo mais objetivo e rápido. Mas, dependendo do caso, pode ainda ser mais encurtado. Digamos que agora eu queira algo como o caso abaixo:

$resultado = $a ? $a : 'b';

Existe, desde o PHP 5.3 uma forma mais curta de fazer essa mesma comparação:

$resultado = $a ?: 'b';

Com isso já conseguimos economizar um pouco mais de código. Mas ainda existe um pequeno problema nessa abordagem: ela só funciona bem, se eu tiver certeza que $a existe, pois o operador não faz esse teste, e se $a não existir, será gerado um mensagem de NOTICE dizendo que a variável não foi declarada. Ele funciona muito bem, por exemplo, dentro de uma função:

function teste($a) {
    return $a ?: 'b';
}

Mas, caso eu precise testar se $a foi declarado, ou seja, se o que eu quero é o equivalente ao código abaixo:

$resultado = isset($a) ? $a : 'b';

Eu ainda posso usar o operador de coalescência nula, ou operador ??, que foi criado no PHP 7:

$resultado = $a ?? 'b';

Essa é uma forma muito prática, e muito útil, principalmente se você quer utilizar algo que foi passado como parâmetro na requisição, como $_GET ou $_POST, e queria definir um valor padrão, caso o parâmetro não tenha sido passado. Veja o exemplo:

$user = $_GET['user'] ?? 'guest';

Mas então, você pode estar se perguntando pra que ainda existe o operador ?: se o ?? já resolve, não é? Bem, perceba que, no primeiro exemplo, o ?? não verifica se $a é verdadeiro, ele apenas verifica se ele foi declarado e não é nulo. Veja como o resultado seria diferente nos seguintes casos:

$a = 0;
$resultado = $a ?: 'b';  // retorna 'b'
$resultado = $a ?? 'b';  // retorna 0

Ou seja, ?: testou se $a é um valor válido e não vazio, enquanto ?? testou apenas se $a foi declarado e não é nulo, independente de seu valor. É preciso tomar muito cuidado com isso, levando em conta o que você queira que seja testado.

Uma outra coisa muito interessante desses operadores ?: e ?? é a possibilidade de concatenar os testes, simplificando e encurtando ainda mais o código:

$resultado = $a ?? $b ?? $c ?? 'd';

Esse código, se usado com o operador ternário comum, equivaleria a:

$resultado = isset($a) && $a !== null ? $a
            : (isset($b) && $b !== null ? $b
            : (isset($c) && $c !== null ? $c : 'd'));

Ou, usando ifs:

if (isset($a) && $a !== null) {
    $resultado = $a;
} elseif (isset($b) && $b !== null) {
    $resultado = $b;
} elseif (isset($c) && $c !== null) {
    $resultado = $c;
} else {
    $resultado = 'd';
}

E aí, qual a melhor forma? ^__^

Comments