PHP null

No cadastro da lojinha, a Ana pede o telefone dos clientes, mas o campo é opcional. Como guardar "este cliente não informou o telefone"? Não é o número zero, nem um texto vazio: é a ausência de valor. Para isso, o PHP tem um valor especial, null ("nulo"), que quer dizer exatamente "nada aqui". Nesta aula você aprende o que é null, de onde ele aparece sem você pedir, como testá-lo e por que ele não é a mesma coisa que "" e 0.

Você vai aprender
  • O que é null e como escrevê-lo.
  • Os lugares onde o null aparece sozinho (variável inexistente, chave que não existe, função sem return).
  • Como testar: is_null, === null e isset.
  • A diferença entre null, "" (texto vazio) e 0 (zero).
  • O atalho ?? para "use isto, ou um valor padrão se for null".
  • Os avisos e erros de usar null onde o PHP esperava outra coisa.

Os programas desta aula rodaram com o PHP 8.5 na máquina fictícia da Ana, na pasta ~/site.


A ideia: o campo em branco que ninguém preencheu

Pense em três clientes da Ana e na pergunta "quantos filhos você tem?":

  • A Bia respondeu 0. Ela tem zero filhos: é uma resposta, um número.
  • O Caio apagou o que tinha escrito e deixou o campo em branco: ele respondeu, com um texto vazio.
  • A Duda nunca viu a pergunta: o formulário antigo não tinha esse campo. Não existe resposta.

Em PHP, a resposta da Bia é 0 (int), a do Caio é "" (string vazia) e a da Duda é null. Três coisas diferentes. null é o único valor que diz "não há valor nenhum aqui".


1. Escrever e mostrar null

<?php
$telefone = null;
var_dump($telefone);
echo "[", $telefone, "]\n";
var_dump(get_debug_type($telefone));
$ php nulo.php
NULL                     « o var_dump mostra só o tipo: não há valor para mostrar
[]                       « o echo não mostra nada
string(4) "null"        « o tipo se chama null
null
A palavra que representa "nenhum valor". Sem aspas: "null" com aspas seria um texto de 4 letras. O PHP aceita NULL e Null também; o costume moderno é null em minúsculas.
NULL (no var_dump)
O var_dump escreve em maiúsculas, por tradição. É o mesmo valor.
[]
Para o echo, null vira texto vazio, como o false (aula Booleanos). Por isso, investigue sempre com var_dump.

null é ao mesmo tempo um tipo e o único valor desse tipo: o tipo null só tem um valor possível (veja Tipos de Dados).


2. De onde vem o null

Você pode escrever null de propósito, mas muitas vezes ele aparece sozinho:

SituaçãoExemploAviso?
Atribuição de propósito$telefone = null;Não
Variável que não existevar_dump($naoExiste);Warning: Undefined variable
Chave de array que não existe$lista["b"]Warning: Undefined array key
Função que não devolve nadauma função sem returnNão
Dados de fora (JSON, banco de dados){"telefone": null}Não
<?php
var_dump($naoExiste);
$lista = ["a" => 1];
var_dump($lista["b"]);
function semRetorno() { $a = 1; }
var_dump(semRetorno());
$ php origens.php

Warning: Undefined variable $naoExiste in /home/ana/site/origens.php on line 2
NULL                     « a variável não existe: vale null, com aviso

Warning: Undefined array key "b" in /home/ana/site/origens.php on line 4
NULL                     « o array não tem a chave "b": null, com aviso
NULL                     « a função não tem return: devolve null

Os dois avisos são sinais de um provável erro de digitação ou de lógica (você vai entender os arrays em Arrays Associativos e as funções em Funções). Já o null da função sem return vem quieto. É por isso que é bom saber que ele existe.


3. Testar se é null

Há três formas de perguntar. Duas são equivalentes; a terceira é parecida, mas não igual:

<?php
$telefone = null;
var_dump(is_null($telefone));
var_dump($telefone === null);
var_dump(isset($telefone));
$ php testar.php
bool(true)               « é null?
bool(true)               « é idêntico a null?
bool(false)              « existe e NÃO é null?
is_null($x)
"É nulo?". Função que devolve true se o valor é null.
$x === null
"É idêntico a null?". Faz o mesmo com o operador de comparação estrita (aula Comparação). É a forma mais usada em código moderno.
isset($x)
"Está definida?". É o contrário: true se existe e não é null. E tem um superpoder: não dá Warning quando a variável não existe (aula Variáveis).

A diferença aparece quando a variável nem existe:

<?php
var_dump(is_null($naoExiste));
var_dump(isset($naoExiste));
$ php inexistente.php

Warning: Undefined variable $naoExiste in /home/ana/site/inexistente.php on line 2
bool(true)               « is_null reclama, depois responde
bool(false)              « isset responde em silêncio

Qual usar? Se a variável com certeza existe e você quer saber se é null: === null (ou is_null). Se ela pode nem existir (um campo de formulário, uma chave de array): isset.

Experimente: troque o valor de $telefone por "", 0, "0" e "99999-1234". Em quais casos is_null dá true? E isset? Depois apague a linha 2 inteira e rode de novo.

<?php
$telefone = null;
var_dump(is_null($telefone));
var_dump(isset($telefone));

4. null, "" e 0 não são a mesma coisa

Voltando às três clientes. Veja como cada teste responde para cada uma:

<?php
$duda = null;   // não respondeu
$caio = "";     // respondeu em branco
$bia = 0;       // respondeu zero
var_dump(is_null($duda), is_null($caio), is_null($bia));
var_dump(isset($duda), isset($caio), isset($bia));
var_dump(empty($duda), empty($caio), empty($bia));
$ php tres.php
bool(true)               « is_null: só a Duda
bool(false)
bool(false)
bool(false)              « isset: Caio e Bia "existem"
bool(true)
bool(true)
bool(true)               « empty: os três parecem "vazios"!
bool(true)
bool(true)
null""0
Quer dizernão há valortexto sem caractereso número zero
Tiponullstringint
is_null / === nulltruefalsefalse
issetfalsetruetrue
empty / (bool) é falsosimsimsim
echo mostranadanada0

A lição: empty e o if ($x) jogam os três no mesmo saco, porque os três são "falsos" (aula Booleanos). Quando a diferença importa, pergunte com === null, === "" ou === 0.

Cuidado com == (dois iguais)

A comparação "frouxa" == converte os tipos antes de comparar, e acha que null é igual a "", a 0 e a false:

$ php frouxo.php             « var_dump(null == "", null == 0, null == false, null === "", null === 0);
bool(true)
bool(true)
bool(true)
bool(false)                  « com três iguais, só null é idêntico a null
bool(false)

Use sempre ===. A explicação completa está em Comparação (== e ===).


5. Valor padrão com ??

Muito do trabalho com null é "se não tiver valor, use um padrão". O PHP tem um operador só para isso, o ?? (chamado null coalescing, "união com nulo"):

<?php
$nome = null;
echo "Olá, " . ($nome ?? "visitante") . "\n";
$nome = "Ana";
echo "Olá, " . ($nome ?? "visitante") . "\n";
$ php padrao.php
Olá, visitante           « $nome é null: usa o padrão
Olá, Ana                 « $nome tem valor: usa o valor

Leia $nome ?? "visitante" como "$nome, ou, se for null (ou nem existir), "visitante"". Como o isset, ele não dá Warning para variável inexistente. Repare que o ?? só olha o null: um 0 ou um "" passam direto. O ??, o ??= e o ?-> estão explicados em ?? e ?->.


6. null onde o PHP esperava outra coisa

O que acontece quando um null "escapa" e entra numa conta, numa função ou num objeto? Depende do lugar:

<?php
var_dump(null + 5);
var_dump(null . "abc");
var_dump(strlen(null));
$ php escapou.php
int(5)                   « na conta, null vale 0
string(3) "abc"         « no texto, null vale ""

Deprecated: strlen(): Passing null to parameter #1 ($string) of type string is deprecated in /home/ana/site/escapou.php on line 4
int(0)

A última linha mostra um Deprecated ("obsoleto"): passar null para uma função do PHP que espera texto ainda funciona, mas foi marcado para deixar de funcionar numa versão futura. Passing null to parameter #1 ($string) of type string = "passando null para o parâmetro nº 1 ($string), que é do tipo string". Corrija sempre que aparecer.

Com objetos (assunto do Nível 3), o null é mais grave:

<?php
$cliente = null;
echo $cliente->nome;
echo "\nfim\n";
echo $cliente->getNome();
$ php objeto-nulo.php

Warning: Attempt to read property "nome" on null in /home/ana/site/objeto-nulo.php on line 3

fim

Fatal error: Uncaught Error: Call to a member function getNome() on null in /home/ana/site/objeto-nulo.php:5
Stack trace:
#0 {main}
  thrown in /home/ana/site/objeto-nulo.php on line 5

Ler uma propriedade de null dá Warning (Attempt to read property "nome" on null = "tentativa de ler a propriedade nome em null"); chamar um método em null é fatal (Call to a member function getNome() on null = "chamada de um método getNome() em null"). Esse é um dos erros mais comuns do PHP. O operador ?-> (?? e ?->) foi criado para ele.


Quando dá errado

Deprecated: ...: Passing null to parameter #1 ($string) of type string is deprecated

O que significa: uma variável que você passou para uma função (como strlen, trim, htmlspecialchars) valia null. Ainda funciona, mas vai virar erro no futuro.

Como consertar: descubra por que a variável é null (campo não enviado? chave errada?) ou dê um padrão: strlen($nome ?? "").

Fatal error: Uncaught Error: Call to a member function ...() on null

O que significa: a variável antes da seta -> deveria ter um objeto, mas tem null. Típico de uma busca que não encontrou nada ("busque o cliente 42" e o cliente não existe).

Como consertar: teste com if ($cliente === null) antes, ou use ?->.

Warning: Undefined array key "..." seguido de um NULL

O que significa: você pediu uma chave que o array não tem, e recebeu null.

Como consertar: confira o nome da chave, ou use $lista["b"] ?? "padrão" quando a chave pode mesmo faltar.

Um campo com 0 ou "" foi tratado como "não informado"

O que significa: o código testou com empty ou if (!$x), que juntam null, "" e 0.

Como consertar: teste só o null: $x === null.


Referência rápida

EscritaO que fazCom null
$x = null;Guarda "nenhum valor"
is_null($x)É null?true (Warning se $x não existe)
$x === nullÉ idêntico a null?true
isset($x)Existe e não é null?false (sem Warning)
$x ?? $padrao$x, ou o padrão se for null/inexistenteo padrão
unset($x);Apaga a variável (depois, ela "vale" null)
var_dump($x)MostraNULL

Exercícios

1. Testar null

Complete com o operador de comparação estrita:

var_dump($telefone null);

2. Valor padrão

Complete para mostrar "sem e-mail" quando $email for null:

echo $email "sem e-mail";

3. Qual o resultado de isset($x) depois de $x = 0;?

4. Uma função sem return devolve…

5. O que var_dump(null == 0); mostra?

Missão final: a ficha do cliente

Missão: a ficha mostra Telefone: em branco porque o telefone é null. Use o ?? para mostrar não informado no lugar de qualquer campo null. Atenção: Filhos: 0 deve continuar mostrando o zero (ele é uma resposta!).

Nome: Duda
Telefone: não informado
Filhos: 0
<?php
$nome = "Duda";
$telefone = null;
$filhos = 0;
echo "Nome: " . $nome . "\n";
echo "Telefone: " . $telefone . "\n";
echo "Filhos: " . $filhos . "\n";
<?php
$nome = "Duda";
$telefone = null;
$filhos = 0;
echo "Nome: " . ($nome ?? "não informado") . "\n";
echo "Telefone: " . ($telefone ?? "não informado") . "\n";
echo "Filhos: " . ($filhos ?? "não informado") . "\n";

Resumo

  • null = "nenhum valor". É um tipo com um valor só. Escreva sem aspas.
  • Aparece sozinho: variável inexistente e chave inexistente (com Warning), função sem return, dados de JSON e banco.
  • Teste com === null ou is_null; use isset quando a variável pode nem existir.
  • null, "" e 0 são diferentes, mas empty, if ($x) e == os confundem. Prefira ===.
  • $x ?? "padrão" dá um valor padrão quando $x é null.
  • null numa função que espera texto dá Deprecated; chamar método em null dá Fatal error.