# Il sistema dei tipi di PHP

> Il sistema dei tipi di PHP spiegato: tipi di dati, dichiarazioni da PHP 7.1 a 8.3, strict_types e confronti non rigorosi, con esempi e legame con la sicurezza.

Fonte: https://phpsos.de/it/php/typsystem/  
Stato: 25/10/2026  
Fornitore: PHP SOS, Assistenza di emergenza PHP e sicurezza dei server. Assistenza immediata su WhatsApp: https://wa.me/491736494914?text=Buongiorno%20PHP%20SOS%2C%20abbiamo%20bisogno%20di%20aiuto%20con%20il%20nostro%20server%20PHP.%20Azienda%3A%20%E2%80%A6%20Sito%20web%3A%20%E2%80%A6

**In breve:** PHP è tipizzato dinamicamente: il tipo di un valore è definito solo in fase di esecuzione e, senza ulteriori indicazioni, PHP converte automaticamente i valori quando serve. Da PHP 7, però, parametri, valori di ritorno e proprietà possono essere dotati di tipi, e `declare(strict_types=1)` rende rigoroso il controllo. Chi conosce le regole e usa confronti stretti con `===` evita un'intera classe di errori di logica e di sicurezza.

## Tipizzato dinamicamente, ma non privo di tipi

In PHP, con `$preis = 19.90;` non occorre indicare alcun tipo. PHP riconosce che si tratta di un numero in virgola mobile. Se il valore viene poi concatenato a una stringa, PHP lo converte. Questo comportamento si chiama type juggling, cioè conversione automatica dei tipi. Rende facile iniziare, ma può portare a risultati sorprendenti.

Per chi decide è rilevante perché molte applicazioni PHP più vecchie sono state scritte senza indicazioni di tipo. Un codice del genere è più difficile da verificare e da modernizzare. I progetti più recenti usano i tipi in modo coerente, il che rende gli errori visibili prima e permette all'[analisi statica](https://phpsos.de/it/php/statische-analyse/) con strumenti come PHPStan o Psalm di dare davvero il meglio.

## I tipi di PHP in sintesi

Il manuale PHP indica nove tipi interni che ogni espressione può avere. Di solito vengono suddivisi in tre gruppi:

| Gruppo | Tipi | Esempio |
|---|---|---|
| Tipi scalari | `bool`, `int`, `float`, `string` | `true`, `42`, `3.5`, `"Text"` |
| Tipi composti | `array`, `object`, `callable` | `[1, 2]`, `new DateTime()` |
| Tipi speciali | `null`, `resource` | `null`, un file aperto |

Per i controlli di tipo il manuale raccomanda le funzioni `is_*()`, come `is_int()`. Per l'analisi è adatta `get_debug_type()`, che da PHP 8.0.0 restituisce i nomi di tipo di uso comune, mentre la più vecchia `gettype()` restituisce ad esempio `"integer"` e `"double"`.

Accanto alla conversione automatica esiste quella esplicita: con un cast come `(int) $wert` o con `settype()` è il codice stesso a stabilire quale tipo debba avere un valore. È una pratica comune per i dati dei moduli, perché tutto ciò che arriva tramite `$_GET` o `$_POST` è inizialmente una stringa o un array. Un cast, però, non verifica se il valore avesse senso: da `"abc"` si ottiene in silenzio `0`. Per i dati in ingresso, un vero controllo con `filter_var()` è quindi di solito la scelta migliore.

Anche classi e interfacce sono tipi in PHP. Una funzione può quindi richiedere che un parametro sia un oggetto di una determinata classe o che soddisfi una determinata interfaccia. Come interagiscono classi, interfacce ed enum lo spiega la pagina [Programmazione a oggetti in PHP](https://phpsos.de/it/php/objektorientierung/).

## Dichiarazioni di tipo: da PHP 7.1 a 8.3

Le dichiarazioni di tipo stabiliscono quali valori una funzione accetta e restituisce. Il sistema dei tipi è cresciuto nel corso di molte versioni. Secondo il registro delle modifiche del manuale sono state aggiunte, tra le altre, queste possibilità:

| Versione | Novità |
|---|---|
| 7.1.0 | tipi nullable (`?int`), `void`, `iterable` |
| 7.2.0 | `object` |
| 7.4.0 | proprietà di classe tipizzate |
| 8.0.0 | tipi union (più tipi ammessi in un'unica indicazione), `mixed`, tipo di ritorno `static` |
| 8.1.0 | tipi intersection (`A&B`), tipo di ritorno `never` |
| 8.2.0 | tipi DNF, tipo letterale `true`, `null` e `false` come tipi autonomi |
| 8.3.0 | costanti tipizzate di classi, interfacce, trait ed enum |

DNF sta per forma normale disgiuntiva e consente combinazioni come `(A&B)|null`. Chi pianifica le versioni di PHP vede da questa tabella anche quali strumenti del linguaggio un'applicazione presuppone.

## strict_types: conversione o TypeError

Senza altre indicazioni PHP lavora in modalità con conversione. Una funzione con parametri `int` accetta allora anche `1.5` e ne ricava `1`; da PHP 8.1 questa conversione con perdita è contrassegnata come deprecata. Con `declare(strict_types=1)` all'inizio del file, PHP genera invece un `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, invece di 3 in silenzio
```

Due sfumature sono importanti. Primo: `strict_types` vale per le chiamate effettuate dal file in cui compare, non per le funzioni ivi definite. Se un file senza `strict_types` chiama la stessa funzione, si converte. Secondo: un intero dove ci si aspetta un numero in virgola mobile è ammesso anche in modalità rigorosa.

## Confronti non rigorosi e rigorosi

L'operatore `==` confronta dopo la conversione di tipo, `===` confronta valore e tipo senza conversione. Il manuale raccomanda nella maggior parte dei casi `===` e `!==`, perché le regole di conversione non sono sempre evidenti.

```php
<?php
var_dump(0 == "a");    // PHP 7: true,  PHP 8: false
var_dump("1" == "01"); // true, entrambe sono stringhe numeriche
var_dump("1" === "01");// false, stesso tipo, ma un'altra stringa
var_dump(1 == true);   // true
var_dump(1 === true);  // false
```

Con PHP 8.0 i confronti tra numeri e stringhe non numeriche sono diventati più sensati. Le applicazioni più vecchie possono comportarsi in modo diverso dopo l'upgrade, ad esempio nei blocchi `switch`. L'espressione `match`, introdotta anch'essa con PHP 8.0, confronta sempre in modo rigoroso. Come i confronti non rigorosi portino a vulnerabilità, ad esempio nei controlli di token o password, lo descrive l'articolo [Type juggling: i confronti non rigorosi come rischio per la sicurezza](https://phpsos.de/it/blog/type-juggling-php/).

## Tipi, upgrade e PHP2Shell

Un sistema dei tipi rigoroso rende il codice applicativo più robusto, ma non protegge dagli errori nell'interprete stesso. Le vulnerabilità PHP2Shell CVE-2026-109618 e CVE-2026-109619 si trovano nella gestione della memoria e delle richieste di PHP. Sono corrette in PHP 8.5.12, 8.4.27, 8.3.36 e 8.2.35; in seguito tutti i processi PHP devono essere riavviati.

Il sistema dei tipi gioca comunque un ruolo, e precisamente nell'upgrade. Le applicazioni ancora ferme a PHP 8.1 o precedenti non ricevono più aggiornamenti ufficiali dal progetto PHP. Un codice ben tipizzato è molto più facile da portare a una versione supportata, perché gli strumenti individuano per tempo le incompatibilità. Per i progetti più datati è utile la nostra [migrazione a una versione di PHP supportata](https://phpsos.de/it/leistungen/php-migration-legacy/).

> **Consiglio:**
> Attivi `strict_types` gradualmente nei file nuovi e in quelli rivisti. Così la sicurezza dei tipi cresce senza che il codice vecchio si rompa di colpo.

## Come aiuta concretamente PHP SOS?

- Verifichiamo quale versione di PHP la Sua applicazione richiede come minimo e la confrontiamo con le versioni corrette.
- Eseguiamo l'analisi statica sul codice e segnaliamo i punti con confronti non rigorosi in controlli rilevanti per la sicurezza.
- Pianifichiamo gli upgrade in modo che le regole di confronto modificate vengano testate prima.
- Installiamo l'aggiornamento di PHP, riavviamo tutti i worker e documentiamo lo stato.


## Domande frequenti

**PHP è tipizzato in modo forte o debole?**  
PHP è tipizzato dinamicamente: il tipo di una variabile è definito solo in fase di esecuzione. Senza strict_types PHP converte i valori quando serve. Con le dichiarazioni di tipo e strict_types il codice può però diventare molto rigoroso.

**Che cosa fa declare(strict_types=1)?**  
Disattiva la conversione automatica dei valori scalari per le chiamate effettuate dal file in questione. Se un valore non corrisponde al tipo dichiarato, PHP genera un TypeError. Unica eccezione è un intero dove ci si aspetta un numero in virgola mobile.

**Perché 0 == "a" è falso in PHP 8 ma vero in PHP 7?**  
Fino a PHP 7, nel confronto con un numero una stringa non numerica veniva convertita in numero e "a" diventava 0. Da PHP 8.0 in questo caso PHP non confronta più in modo numerico, e il risultato è false.

**I tipi proteggono dalle vulnerabilità in PHP stesso?**  
No. I tipi prevengono errori nel codice della Sua applicazione. Le vulnerabilità nell'interprete come PHP2Shell si chiudono solo con un aggiornamento di PHP. Le funzioni di tipo moderne richiedono però versioni di PHP recenti e sono quindi una buona occasione per l'upgrade.

## Fonti

- [Manuale PHP: dichiarazioni di tipo](https://www.php.net/manual/de/language.types.declarations.php)
- [Manuale PHP: introduzione ai tipi](https://www.php.net/manual/de/language.types.intro.php)
- [Manuale PHP: operatori di confronto](https://www.php.net/manual/de/language.operators.comparison.php)
- [Rilascio di PHP 8.0](https://www.php.net/releases/8.0/en.php)
