?? retorna o valor da esquerda se ele existir e não for null, senão o valor da direita: $name = $_GET['name'] ?? 'Guest';. Ao contrário de ler a chave diretamente, ele nunca avisa quando a variável ou a chave do array está ausente.
Na primeira execução não há query string, então os dois padrões são usados. Clique num link da aba Page e o script roda de novo com $_GET preenchido. Ler $_GET["name"] sem ?? nessa primeira execução imprimiria Warning: Undefined array key "name" numa configuração normal do PHP. Mais sobre dados da requisição na página sobre _POST.
?? é uma verificação isset() abreviada
$a ?? $b significa exatamente isset($a) ? $a : $b. Funciona com variáveis, chaves de array em qualquer profundidade e propriedades de objetos, e para na primeira peça ausente sem reclamar.
A verificação é a mesma que o isset faz, então uma chave que existe com o valor null também recebe o padrão.
Encadear ?? para tentar várias fontes
?? é associativo à direita e você pode encadear quantos quiser. O PHP retorna o primeiro operando que está definido e não é null.
??= só atribui quando é null
$a ??= $b guarda $b em $a só quando $a não está definido ou é null. É o jeito mais curto de preencher padrões ou de calcular algo uma vez e reutilizar.
O lado direito do ??= só é avaliado quando a atribuição acontece, e é por isso que computing 4 aparece uma vez.
?? ou ?: (ternário curto)
?? testa null. ?: testa se o valor é verdadeiro. Com valores como 0, "" e "0" eles dão respostas diferentes:
Uma quantidade "0" é uma entrada válida: ?? a mantém, ?: a substitui. ?: sozinho avisaria sobre a chave ausente, e é por isso que o bloco o envolve como ($inputs[$key] ?? null) ?: .... A página sobre o operador ternário explica o ?: em si.
O operador nullsafe ?->
?-> é a versão para objetos da mesma ideia, adicionada no PHP 8. Se o objeto à esquerda for null, a cadeia inteira para e retorna null em vez de lançar um Error como Call to a member function getAddress() on null. Coloque ?? no fim para ter um padrão.
O usuário 2 existe, mas não tem endereço, e o usuário 3 nem existe. Os dois chegam ao padrão ?? "unknown" sem erro.
Erro comum: ?? tem precedência baixa
?? tem ligação mais fraca que . e os operadores aritméticos. Então em "Count: " . $count ?? 0, o PHP primeiro monta a string "Count: " . $count, que nunca é null, e o padrão nunca é usado.
Coloque a expressão com ?? entre parênteses sempre que ela estiver dentro de uma expressão maior.
Perguntas frequentes
O que significa ?? no PHP?
?? é o operador de coalescência nula. $a ?? $b retorna $a se ele existir e não for null, senão $b. É a forma curta de isset($a) ? $a : $b e não gera aviso quando $a ou uma chave de array está indefinida.
Qual a diferença entre ?? e ?: no PHP?
?? só cai no padrão quando o lado esquerdo é null ou não está definido, então 0 ?? 5 é 0 e '' ?? 'x' é ''. ?: cai no padrão sempre que o lado esquerdo é falso, então 0 ?: 5 é 5. ?: também avisa sobre variáveis e chaves indefinidas, ?? não.
O que faz ??= no PHP?
$a ??= $b atribui $b a $a só se $a for null ou não estiver definido; caso contrário, deixa $a como está. É a forma curta de $a = $a ?? $b; e foi adicionado no PHP 7.4.
O que é o operador nullsafe ?-> no PHP?
$obj?->method() chama o método só quando $obj não é null; se for null, a cadeia inteira retorna null em vez de lançar um erro. Combine com ?? para ter um padrão: $user?->getAddress()?->city ?? 'unknown'. Ele foi adicionado no PHP 8.0.