A diretiva declare(strict_types=1)
é amplamente utilizada no PHP, mas nem todos entendem o que ela faz na prática. Nesse texto nós vamos entender como o comportamento do seu código pode ser alterado ao usar essa diretiva.
Type hints no PHP
O PHP possui o conceito de Type Hints que é basicamente como nós podemos informar os tipos que usaremos em alguns locais como em parâmetros e retornos de funções. Ao informar o tipo de um parâmetro, por exemplo, o PHP irá verificar se o valor passado é compatível com o tipo informado. Por exemplo:
function soma(int $a, int $b): int
{
return $a + $b;
}
soma('test 1', 'test 2'); // Fatal error: Uncaught TypeError: Argument 1 passed to soma() must be of the type int, string given
Repare que ao tentar passar uma string para uma função que espera inteiros, um erro do tipo TypeError
é lançado. Esse tipo de técnica traz mais segurança para nosso código de forma que conhecemos melhor os valores que manipulamos.
Malabarismo com tipos
Embora o PHP possua os famosos e muito úteis type hints, é importante dizer que nem sempre eles são seguidos à risca. O PHP possui outro conceito chamado type juggling (malabarismo de tipos em tradução livre) que é basicamente a conversão de tipos de forma implícita. Essa funcionalidade permite algumas facilidades bem interessantes, principalmente quando nos lembramos que o protocolo HTTP trabalha somente com texto. Se nós recebessemos os dois números para realizar a soma por uma requisição, eles viriam como string
s, então o seguinte código seria executado:
soma('1', '2'); // 3
Embora ainda estejamos passando strings por parâmetro, agora a chamada da função é bem sucedida. Isso acontece, pois o PHP possui algo chamado strings numéricas. O exemplo anterior é um caso onde a conversão automática dos tipos nos ajuda, porém há casos onde isso pode ser um problema. Se nós tentarmos passar números com ponto flutuante, por exemplo, o PHP irá remover a parte decimal dos números:
soma(1.5, 2.5); // 3
Desde a versão 8.1 o PHP emitirá um aviso de obsolência (deprecation notice) quando tentamos converter float
para int
, mas ainda assim o código é executado e o resultado é no mínimo inesperado (para não dizer incorreto).
Impedindo conversões
Para impedir esse comportamento do PHP, nós podemos usar a diretiva declare(strict_types=1)
que irá forçar o PHP a seguir os type hints de forma mais rígida, sem conversões implícitas de tipos. Ao usar essa diretiva, o PHP irá lançar um erro do tipo TypeError
quando tentarmos passar um tipo diferente do esperado, mesmo que seja possível realizar alguma conversão. Sendo assim, se onde eu chamo a função soma
houver a declaração de strict_types
, o código lançará um erro:
<?php
declare(strict_types=1);
function soma(int $a, int $b): int
{
return $a + $b;
}
soma('1', '2'); // Fatal error: Uncaught TypeError: Argument 1 passed to soma() must be of the type int, string given
soma(1.5, 2.5); // Fatal error: Uncaught TypeError: Argument 1 passed to soma() must be of the type int, float given
Um detalhe muito importante é que a diretiva declare(strict_types=1)
deve ser declarada no início do arquivo, antes de qualquer código.
Múltiplos arquivos
A diretiva declare
agirá no arquivo onde ela for declarada, então pode acontecer de termos um arquivo com strict_types=1
e outro sem. Nesse cenário, o PHP vai se comportar seguindo o que for declarado no arquivo que chama a função e não no arquivo que a declara. Exemplo:
<?php
// arquivo functions.php
declare(strict_types=1);
function soma(int $a, int $b) {
return $a + $b;
}
?>
<?php
// arquivo index.php
require_once 'functions.php';
echo soma('1', '2'); // 3
?>
Repare que mesmo o arquivo functions.php
possuindo a diretiva, o arquivo que executa a função é o index.php
e ele não informa a diretiva, logo, ela estará desabilitada. Já no caso contrário, o seguinte ocorrerá:
// arquivo functions.php
function soma(int $a, int $b) {
return $a + $b;
}
?>
<?php
// arquivo index.php
declare(strict_types=1);
require_once 'functions.php';
echo soma('1', '2'); // Fatal error: Uncaught TypeError: Argument 1 passed to soma() must be of the type int, string given
?>
Mesmo o arquivo functions.php
não informando a diretiva declare(strict_types=1)
o erro acontece, pois no arquivo index.php
é onde a chamada acontece e ele possui a diretiva.
Conclusão
Tipos em PHP podem ser um assunto espinhoso porque além de complexo, nem todo dev concorda em como utilizá-los. Uns (como eu) acreditam que quanto mais estrito, melhor. Outros acreditam que type hints são um desperdício. Mais uma coisa eu acredito que seja unânime: é muito importante para nós, como devs PHP, entender como os tipos funcionam na linguagem com a qual trabalhamos.
Se você deseja explorar ainda mais o tema de tipos em PHP, recomendo a leitura de um artigo abrangente no blog Codamos. O conteúdo discute detalhadamente os diversos tipos em PHP, suas manipulações e conversões, e oferece uma análise mais aprofundada sobre strict_types
, inclusive com trechos de código em C do PHP. Para acessar o artigo completo, visite este link. E se você quiser aprender mais sobre PHP, há muitos cursos gravados por mim lá na Alura. Aqui tem um cupom de 15% de desconto para assinar a plataforma.