# O sistema de tipos do PHP

> O sistema de tipos do PHP explicado: tipos de dados, declarações de tipo do PHP 7.1 ao 8.3, strict_types e comparações laxas, com exemplos e ligação à segurança.

Fonte: https://phpsos.de/pt/php/typsystem/  
Atualizado em: 25/10/2026  
Prestador: PHP SOS, Assistência de emergência PHP e segurança de servidores. Ajuda imediata por WhatsApp: https://wa.me/491736494914?text=Ol%C3%A1%2C%20PHP%20SOS%2C%20precisamos%20de%20ajuda%20com%20o%20nosso%20servidor%20PHP.%20Empresa%3A%20%E2%80%A6%20Site%3A%20%E2%80%A6

**Em resumo:** O PHP tem tipagem dinâmica: o tipo de um valor só é conhecido em tempo de execução e, sem mais indicações, o PHP converte automaticamente os valores quando necessário. Desde o PHP 7, porém, é possível atribuir tipos a parâmetros, retornos e propriedades, e `declare(strict_types=1)` torna a verificação rigorosa. Quem conhece as regras e usa comparações estritas com `===` evita toda uma classe de erros de lógica e de segurança.

## Tipagem dinâmica, mas não sem tipos

Em PHP, com `$preis = 19.90;` não é preciso indicar um tipo. O PHP reconhece que se trata de um número de vírgula flutuante. Se o valor for mais tarde combinado com uma cadeia de caracteres, o PHP converte-o. Este comportamento chama-se type juggling, ou seja, conversão automática de tipos. Facilita a iniciação, mas pode levar a resultados surpreendentes.

Para quem decide, isto é relevante porque muitas aplicações PHP mais antigas foram escritas sem indicações de tipo. Esse código é mais difícil de verificar e de modernizar. Os projetos mais recentes usam os tipos de forma consistente, o que torna os erros visíveis mais cedo e só assim permite que a [análise estática](https://phpsos.de/pt/php/statische-analyse/) com ferramentas como o PHPStan ou o Psalm tenha verdadeiro efeito.

## Os tipos do PHP em resumo

O manual do PHP indica nove tipos internos que qualquer expressão pode ter. Habitualmente são divididos em três grupos:

| Grupo | Tipos | Exemplo |
|---|---|---|
| Tipos escalares | `bool`, `int`, `float`, `string` | `true`, `42`, `3.5`, `"Text"` |
| Tipos compostos | `array`, `object`, `callable` | `[1, 2]`, `new DateTime()` |
| Tipos especiais | `null`, `resource` | `null`, um ficheiro aberto |

Para verificações de tipo, o manual recomenda as funções `is_*()`, como `is_int()`. Para inspeção, é adequado o `get_debug_type()`, que desde o PHP 8.0.0 devolve os nomes de tipo habituais, enquanto o `gettype()`, mais antigo, devolve por exemplo `"integer"` e `"double"`.

Além da conversão automática, existe a explícita: com um cast como `(int) $wert` ou com `settype()`, o próprio código determina que tipo um valor deve ter. É habitual com entradas de formulários, porque tudo o que chega através de `$_GET` ou `$_POST` é, de início, uma cadeia de caracteres ou um array. Um cast, porém, não verifica se o valor fazia sentido: `"abc"` passa silenciosamente a `0`. Para entradas, uma verificação a sério com `filter_var()` é por isso, em regra, a melhor escolha.

As classes e as interfaces são também tipos em PHP. Uma função pode, portanto, exigir que um parâmetro seja um objeto de uma determinada classe ou cumpra uma determinada interface. Como interagem classes, interfaces e enums explica-o a página [Programação orientada a objetos em PHP](https://phpsos.de/pt/php/objektorientierung/).

## Declarações de tipo: do PHP 7.1 ao 8.3

As declarações de tipo determinam que valores uma função aceita e devolve. O sistema de tipos foi crescendo ao longo de muitas versões. Segundo o registo de alterações do manual, foram acrescentadas, entre outras, estas possibilidades:

| Versão | Novidade |
|---|---|
| 7.1.0 | tipos anuláveis (`?int`), `void`, `iterable` |
| 7.2.0 | `object` |
| 7.4.0 | propriedades de classe com tipo |
| 8.0.0 | tipos união (vários tipos permitidos numa só indicação), `mixed`, tipo de retorno `static` |
| 8.1.0 | tipos intersecção (`A&B`), tipo de retorno `never` |
| 8.2.0 | tipos DNF, tipo literal `true`, `null` e `false` como tipos autónomos |
| 8.3.0 | constantes de classe, interface, trait e enum com tipo |

DNF significa forma normal disjuntiva e permite combinações como `(A&B)|null`. Quem planeia versões do PHP vê também, nesta tabela, que recursos da linguagem uma aplicação pressupõe.

## strict_types: conversão ou TypeError

Sem mais indicações, o PHP trabalha em modo de conversão. Uma função com parâmetros `int` aceita então também `1.5` e faz dele `1`; desde o PHP 8.1, esta conversão com perda está marcada como obsoleta. Com `declare(strict_types=1)` no início do ficheiro, o PHP lança em vez disso um `TypeError`.

```php
<?php
declare(strict_types=1);

function summe(int $a, int $b): int
{
    return $a + $b;
}

echo summe(1, 2);      // 3
echo summe(1.5, 2.5);  // TypeError, em vez de silenciosamente 3
```

Há duas subtilezas importantes. Em primeiro lugar, o `strict_types` aplica-se às chamadas feitas a partir do ficheiro em que consta, não às funções aí definidas. Se um ficheiro sem `strict_types` chamar a mesma função, há conversão. Em segundo lugar, um número inteiro onde se espera um número de vírgula flutuante é permitido também no modo estrito.

## Comparações laxas e estritas

O operador `==` compara depois de uma conversão de tipos, o `===` compara valor e tipo sem conversão. O manual recomenda, na maioria dos casos, `===` e `!==`, porque as regras de conversão nem sempre são óbvias.

```php
<?php
var_dump(0 == "a");    // PHP 7: true,  PHP 8: false
var_dump("1" == "01"); // true, ambas são cadeias de caracteres numéricas
var_dump("1" === "01");// false, mesmo tipo, mas cadeia de caracteres diferente
var_dump(1 == true);   // true
var_dump(1 === true);  // false
```

Com o PHP 8.0, as comparações entre números e cadeias de caracteres não numéricas tornaram-se mais razoáveis. As aplicações mais antigas podem comportar-se de forma diferente depois da atualização, por exemplo em blocos `switch`. A expressão `match`, introduzida também com o PHP 8.0, compara sempre de forma estrita. Como as comparações laxas levam a vulnerabilidades, por exemplo em verificações de tokens ou de palavras-passe, descreve-o o artigo [Type juggling: comparações laxas como risco de segurança](https://phpsos.de/pt/blog/type-juggling-php/).

## Tipos, atualizações e PHP2Shell

Um sistema de tipos rigoroso torna o código da aplicação mais robusto, mas não protege contra erros no próprio interpretador. As vulnerabilidades PHP2Shell CVE-2026-109618 e CVE-2026-109619 estão na gestão de memória e de pedidos do PHP. Estão corrigidas no PHP 8.5.12, 8.4.27, 8.3.36 e 8.2.35; depois, todos os processos PHP têm de ser reiniciados.

O sistema de tipos desempenha, ainda assim, um papel, e é na atualização. As aplicações que ainda estão presas ao PHP 8.1 ou anterior já não recebem atualizações oficiais do projeto PHP. O código bem tipado é muito mais fácil de elevar a uma versão suportada, porque as ferramentas encontram incompatibilidades cedo. Nos projetos mais antigos, ajuda a nossa [migração para uma versão do PHP suportada](https://phpsos.de/pt/leistungen/php-migration-legacy/).

> **Dica:**
> Ative o `strict_types` de forma gradual, em ficheiros novos e revistos. Assim, a segurança de tipos cresce sem que o código antigo deixe de funcionar de uma só vez.

## Como ajuda concretamente a PHP SOS?

- Verificamos que versão do PHP a sua aplicação exige no mínimo e comparamos com as versões corrigidas.
- Executamos a análise estática sobre o código e assinalamos os pontos com comparações laxas em verificações relevantes para a segurança.
- Planeamos as atualizações de modo que as regras de comparação alteradas sejam testadas antes.
- Aplicamos a atualização do PHP, reiniciamos todos os workers e documentamos o estado.


## Perguntas frequentes

**O PHP tem tipagem forte ou fraca?**  
O PHP tem tipagem dinâmica: o tipo de uma variável só é conhecido em tempo de execução. Sem strict_types, o PHP converte valores quando necessário. Com declarações de tipo e strict_types, o código pode, no entanto, tornar-se muito rigoroso.

**O que faz declare(strict_types=1)?**  
Desativa, nas chamadas feitas a partir do respetivo ficheiro, a conversão automática de valores escalares. Se um valor não corresponder ao tipo declarado, o PHP lança um TypeError. A única exceção é um número inteiro onde se espera um número de vírgula flutuante.

**Porque é que 0 == «a» é falso no PHP 8 e verdadeiro no PHP 7?**  
Até ao PHP 7, uma cadeia de caracteres não numérica era convertida num número na comparação com um número, e «a» passava a 0. Desde o PHP 8.0, o PHP deixou de comparar numericamente neste caso e o resultado é false.

**Os tipos protegem contra vulnerabilidades do próprio PHP?**  
Não. Os tipos evitam erros no código da sua aplicação. As vulnerabilidades no interpretador, como o PHP2Shell, só se fecham com uma atualização do PHP. As funcionalidades de tipos modernas pressupõem, porém, versões atuais do PHP e são por isso uma boa ocasião para atualizar.

## Fontes

- [Manual do PHP: declarações de tipo](https://www.php.net/manual/de/language.types.declarations.php)
- [Manual do PHP: introdução aos tipos](https://www.php.net/manual/de/language.types.intro.php)
- [Manual do PHP: operadores de comparação](https://www.php.net/manual/de/language.operators.comparison.php)
- [Lançamento do PHP 8.0](https://www.php.net/releases/8.0/en.php)
