Introdução ao Sistema de Tipos Aprimorado
A versão 8.0 do PHP trouxe avanços significativos para a tipagem estática, oferecendo maior expressividade e segurança. As principais melhorias incluem o suporte nativo a tipos união e um tratamento mais rigoroso para valores nulos. Estas características permitem que desenvolvedores expressem a intenção do código de forma mais clara, capturando erros potenciais em tempo de compilação.
Tipos União (Union Types) em PHP 8.0
Antes do PHP 8.0, declarar que uma função podia aceitar ou retornar múltiplos tipos exigia anotações em docblocks ou verificações manuais. Agora, é possível usar a sintaxe nativa com o caractere |.
Declaração e Utilização Básica
Um tipo união permite que uma variável, parâmetro ou valor de retorno tenha mais de um tipo possível. Considere uma função que pode retornar um inteiro ou um ponto flutuante.
function obterPontuacao(): int|float {
$gerador = new \Random\Randomizer();
return $gerador->getInt(0, 1) ? 95 : 94.5;
}
A assinatura int|float torna o contrato da função explícito. O motor do PHP irá gerar um TypeError se a função tentar retornar um valor que não corresponda a um desses tipos, como uma string.
Aplicação em Propriedades e Parâmetros
Esta funcionalidade é igualmente útil em propriedades de classes e parâmetros de métodos, eliminando a ambiguidade.
class Produto {
public string $nome;
public int|null $quantidadeEmEstoque;
public function __construct(string $nome, int|null $quantidade = null) {
$this->nome = $nome;
$this->quantidadeEmEstoque = $quantidade;
}
public function exibirInfo(): string {
return "Produto: {$this->nome}, Estoque: " . ($this->quantidadeEmEstoque ?? 'Não definido');
}
}
A propriedade $quantidadeEmEstoque e o parâmetro $quantidade aceitam explicitamente tanto um int quanto null. O operador ?int é apenas um atalho para int|null.
Tratamento Seguro de Nulidade
O PHP 8.0 fortalece a programação orientada a objetos ao introduzir uma sintaxe para navegação segura em cadeias de chamadas que podem conter null.
O Operador Nullsafe (?.)
O operador ?. permite encadear chamadas de métodos ou acesso a propriedades de um objeto, retornando null imediatamente se qualquer parte da cadeia for nula, em vez de lançar um erro fatal.
class Endereco {
public ?string $cep;
}
class Usuario {
public ?Endereco $endereco;
}
$usuario = new Usuario();
$usuario->endereco = new Endereco();
$usuario->endereco->cep = '01001-000';
// Com o operador nullsafe
$cep = $usuario->endereco?->cep;
// $cep contém '01001-000'
$usuario->endereco = null;
$cepNulo = $usuario->endereco?->cep;
// $cepNulo contém null (sem erro)
Sem o operador nullsafe, o segundo acesso ($usuario->endereco->cep) geraria um erro "Attempt to read property on null". A nova sintaxe simplifica o código defensivo, especialmente ao lidar com dados de fontes externas.
Casos Práticos e Integrações
Melhorando a Legibilidade em Frameworks como o Laravel
Em frameworks como o Laravel, os tipos união e o operador nullsafe melhoram a clareza dos métodos e redutores de código.
// Exemplo em um Accessor de Eloquent
class Post extends Model {
public function getDataPublicacaoFormatadaAttribute(): ?string {
// O operador nullsafe evita uma verificação if completa
return $this->attributes['data_publicacao']?->format('d/m/Y');
}
}
// Retorno de um método no Controller
protected function respostaJson(mixed $dados): array {
// Declaração clara: o método retorna um array ou uma Collection do Laravel
return is_array($dados) ? $dados : $dados->toArray();
}
Refatoração de Código Legado
Ao migrar de versões anteriores, é comum encontrar verificações manuais de nulidade e tipo. Estas podem ser simplificadas.
// Código pré-PHP 8.0
function processarConfig(?array $config): ?string {
if ($config !== null && isset($config['chave'])) {
return (string) $config['chave'];
}
return null;
}
// Código refatorado para PHP 8.0+ usando tipagem estrita e nullsafe
declare(strict_types=1);
function processarConfig(array|null $config): string|null {
// Encadeamento seguro
return $config?['chave'];
}
A versão refatorada é mais concisa, aproveitando o operador de acesso a índice nullsafe (?['chave']) e a tipagem explícita em strict_types.
Considerações sobre Compatibilidade e Padrões
A adoção desses recursos requer atenção a alguns pontos:
- Análise Estática: Ferramentas como PHPStan e Psalm já suportam os novos tipos união, permitindo a detecção de erros antes da execução.
- Herança e Contratos: As assinaturas de métodos em subclasses ou implementações de interface devem respeitar os tipos união definidos nas classes pais ou interfaces.
- Especificidade: Prefira usar os tipos mais específicos possíveis. Um tipo
int|stringem um parâmetro de uma função de ID de banco de dados pode ser mais adequado do que ummixedgenérico.