---
title: 'PHP 8.2: What’s New — Types, Readonly Classes, Security & Migration | DevSense'
description: 'Guida a PHP 8.2: classi readonly, tipi autonomi null/false/true, tipi DNF, #[SensitiveParameter], estensione Random, deprecazione delle proprietà dinamiche e modifiche non retrocompatibili.'
faq:
    - { question: 'Cosa sono le classi Readonly in PHP 8.2?', answer: 'Una classe readonly contrassegna implicitamente tutte le sue proprietà come readonly. Tutte le proprietà devono essere tipizzate e la classe non supporta proprietà dinamiche. Può ereditare solo da altre classi readonly.' }
    - { question: "In che modo l'attributo #[SensitiveParameter] migliora la sicurezza dell'applicazione?", answer: "L'attributo #[SensitiveParameter] oscura i valori sensibili (come password, chiavi o token) negli stack trace, impedendo la loro fuoriuscita accidentale nei file di log o nell'output degli errori." }
    - { question: "Cos'è la DNF (Disjunctive Normal Form) in PHP 8.2?", answer: 'La DNF consente agli sviluppatori di combinare tipi di unione e intersezione in un formato standardizzato, come `(Countable&Traversable)|null` per metodi che accettano strutture complesse o null.' }
    - { question: 'Perché le proprietà dinamiche sono deprecate in PHP 8.2?', answer: "Le proprietà dinamiche sono deprecate per prevenire bug a runtime causati da errori di battitura nei nomi delle proprietà. Le classi devono dichiarare le proprie proprietà, utilizzare l'attributo `#[AllowDynamicProperties]` o implementare i metodi magici `__set()`/`__get()`." }
published: '2026-05-31'
---
# PHP 8.2: Funzionalità principali

Note pratiche per i team che passano da PHP 8.1.x a 8.2.x: aggiunte al linguaggio, attributi orientati alla sicurezza, gestione più rigorosa delle stringhe e le deprecazioni da ripulire prima del prossimo salto di versione.

## Indice
* [#[SensitiveParameter] e stack trace più sicuri](#sensitive-parameter)
* [Classi Readonly](#readonly-classes)
* [Tipi autonomi (`null`, `false`, `true`) e DNF](#standalone-types-dnf)
* [Costanti nei trait ed enum in espressioni costanti](#traits-constants)
* [INI: `error_log_mode`](#error-log-mode)
* [Estensione Random](#random-extension)
* [Aggiornamenti importanti delle estensioni (cURL, PCRE)](#extension-updates)
* [Modifiche non retrocompatibili (note di migrazione)](#backward-incompatible)
* [Deprecazioni (correggere prima che diventino errori)](#deprecations)
* [Note sulle estensioni e sul runtime](#extensions-notes)
* [Errori comuni](#common-mistakes)
* [Quiz di autovalutazione](#self-test-quiz)

---

PHP 8.2 indirizza fermamente il linguaggio verso l'esplicitezza dei tipi e la sicurezza strutturale. Con l'introduzione delle classi readonly e dei tipi in forma normale disgiuntiva (DNF), gli sviluppatori ottengono un controllo granulare sull'immutabilità degli oggetti e sulle dichiarazioni di tipi complessi. La sicurezza è integrata a livello di linguaggio, consentendo di contrassegnare esplicitamente le credenziali tramite `#[SensitiveParameter]` per evitare che vengano esposte negli stack trace. Tuttavia, questa versione introduce importanti deprecazioni—in particolare le proprietà dinamiche—per intercettare i bug prima della messa in produzione. Ecco la tua guida alla transizione verso PHP 8.2.

<a id="sensitive-parameter"></a>
## #[SensitiveParameter] e stack trace più sicuri

L'attributo `#[\SensitiveParameter]` contrassegna i parametri che devono essere oscurati negli stack trace e negli output di debug, riducendo l'esposizione accidentale di credenziali nei log e nelle pagine di errore.

> [!NOTE]
> **Lo sapevi?**
> L'attributo `#[SensitiveParameter]` funziona nativamente con l'output dei trace delle eccezioni predefinito di PHP. Quando PHP genera uno stack trace, sostituisce il valore del parametro con un oggetto `SensitiveParameterValue`, mascherando completamente la stringa originale nei log!

```php
// app/Services/DatabaseService.php
function connect(#[\SensitiveParameter] string $password): void
{
    throw new RuntimeException('fail');
}
```

Associa questo attributo a pratiche di logging disciplinate e non stampare mai eccezioni grezze in ambiente di produzione.

### Ricetta pratica: contrassegnare i segreti ai confini del sistema

Usa `#[\SensitiveParameter]` sui parametri che potrebbero finire nelle eccezioni (client HTTP, helper di autenticazione). Mantiene utili gli stack trace senza esporre credenziali sensibili.

```php
// app/Clients/ApiClient.php
final class ApiClient
{
    public function __construct(
        private readonly string $baseUrl,
        #[\SensitiveParameter] private readonly string $token,
    ) {}
}
```

---

<a id="readonly-classes"></a>
## Classi Readonly

Una classe può essere dichiarata come `readonly`, rendendo **tutte** le sue proprietà di istanza readonly e richiedendo la loro inizializzazione al momento della costruzione (equivalente ad applicare `readonly` a ciascuna proprietà).

> [!NOTE]
> **Lo sapevi?**
> Una classe readonly impedisce automaticamente la creazione di proprietà dinamiche! Non è nemmeno necessario utilizzare l'attributo `#[AllowDynamicProperties]`, poiché il tentativo di aggiungere una proprietà dinamica a una classe readonly genererà immediatamente un Error.

```php
// app/DTO/Point.php
readonly class Point
{
    public function __construct(
        public int $x,
        public int $y,
    ) {}
}
```

Utilizza questo costrutto per value object immutabili e DTO in cui l'intero grafo di oggetti deve essere congelato dopo la costruzione.

---

<a id="standalone-types-dnf"></a>
## Tipi autonomi (`null`, `false`, `true`) e DNF

PHP 8.2 consente l'uso di **`null`**, **`false`** e **`true`** come tipi autonomi nelle dichiarazioni (e non solo come elementi all'interno di tipi di unione come nelle versioni precedenti).

I tipi **DNF (Disjunctive Normal Form / Forma Normale Disgiuntiva)** consentono di combinare tipi di **unione** e **intersezione** in una forma normalizzata, ad esempio `(A&B)|null`—utile per definire API precise senza perdere la possibilità di accettare null.

```php
// app/Services/ExportService.php
function accepts((Countable&Traversable)|null $c): void {}
```

---

<a id="traits-constants"></a>
## Costanti nei trait ed enum in espressioni costanti

* **Costanti nei trait**: sono ora consentite—utili per condividere configurazioni senza forzare l'ereditarietà da una classe base comune.
* **Proprietà di Enum in espressioni costanti**: è possibile fare riferimento a casi o proprietà di enum in punti in cui sono richieste espressioni costanti, consentendo configurazioni più avanzate a tempo di compilazione.

---

<a id="error-log-mode"></a>
## INI: `error_log_mode`

La direttiva INI **`error_log_mode`** definisce i permessi del file per il log degli errori quando viene creato da PHP—utile per installazioni protette (evitando ad esempio la creazione di file di log leggibili da tutti gli utenti del sistema).

---

<a id="random-extension"></a>
## Estensione Random

L'estensione **Random** consolida ed estende le API per la generazione di numeri casuali, introducendo motori RNG più chiari ed evitando i classici difetti dovuti all'uso isolato di vecchie funzioni ad-hoc. Preferiscila per il nuovo codice che richiede seed riproducibili, algoritmi migliori o testabilità.

### Ricetta pratica: `Randomizer` per token e campionamenti

```php
// app/Services/TokenGenerator.php
$engine = new Random\Engine\Mt19937(random_int());
$randomizer = new Random\Randomizer($engine);
$token = $randomizer->getBytesFromString('0123456789abcdef', 32);
```

Usa un motore con seed fisso nei test per rendere deterministico l'output casuale; usa un motore crittograficamente sicuro quando generi chiavi segrete.

---

<a id="extension-updates"></a>
## Aggiornamenti importanti delle estensioni (cURL, PCRE)

* **cURL**: `CURLINFO_EFFECTIVE_METHOD` espone il metodo HTTP effettivo utilizzato; `curl_upkeep()` aiuta a mantenere attiva la connessione; vengono esposte nuove costanti libcurl dove disponibili.
* **PCRE**: il modificatore **`n` (NO_AUTO_CAPTURE)** rende i gruppi ordinari `()` non catturanti a meno che non siano esplicitamente nominati—comodo per pattern complessi riducendo i riferimenti numerici passati.

---

<a id="backward-incompatible"></a>
## Modifiche non retrocompatibili (note di migrazione)

### Data e ora

* `DateTime::createFromImmutable()` / `DateTimeImmutable::createFromMutable()` utilizzano ora tipi di ritorno **provvisoriamente `static`** (con vincoli più stringenti per gli strumenti di analisi dell'ereditarietà).
* Formati relativi di data: i simboli numerici non consentono più segni multipli (es. `+-2` non è più valido).

### Libreria standard (alto impatto)

* **Conversione maiuscolo/minuscolo ASCII indipendente dalla localizzazione**: `strtolower()`, `strtoupper()`, `lcfirst()`, `ucfirst()`, `ucwords()` e le relative chiamate **non risentono più della localizzazione di sistema (locale-independent)**; si comportano come con la localizzazione `"C"`. Usa **mbstring** per conversioni di maiuscolo/minuscolo localizzate.
* **`str_split('')`** ora restituisce un array vuoto `[]` (in precedenza restituiva `[""]`).
* **`glob()` / `GlobIterator`**: sotto la direttiva `open_basedir`, il comportamento in caso di array vuoto rispetto al valore `false` ed i relativi avvisi sono cambiati—verifica le funzioni di scansione delle directory in ambienti di hosting condivisi.
* **`FilesystemIterator`**: l'opzione `SKIP_DOTS` non è più abilitata forzatamente; imposta i flag esplicitamente se facevi affidamento sul comportamento predefinito precedente.
* **`ksort` / `krsort`**: `SORT_REGULAR` applica in modo uniforme le regole per le stringhe numeriche introdotte in PHP 8.
* **`var_export()`**: i backslash iniziali per i nomi di classe non vengono più omessi (restituisce nomi di classe pienamente qualificati).

### ODBC / PDO_ODBC

Il nome utente e la password vengono **sottoposti a escape** quando aggiunti alle stringhe di connessione—risolve vulnerabilità da injection o stringhe malformate; verifica i test di integrazione con DSN reali.

### SPL

Diversi metodi di `SplFileObject` ora applicano firme in modo più rigoroso; i tipi di ritorno per alcuni metodi sono stati resi più specifici (`hasChildren`, `getChildren`).

---

<a id="deprecations"></a>
## Deprecazioni (correggere prima che diventino errori)

### Proprietà dinamiche

La creazione di **proprietà dinamiche** su classi arbitrarie è deprecata a meno che la classe non utilizzi l'attributo **`#[\AllowDynamicProperties]`** (o estenda classi come `stdClass` che lo consentono). Preferisci l'uso di proprietà dichiarate, `WeakMap` per metadati esterni o definisci esplicitamente i metodi magici `__get`/`__set`.

### Callable parziali

I callable accettati solo da `call_user_func()` ma non richiamabili nella forma `$callable()`—es. `"self::method"`, `"parent::method"`, alcune forme basate su array—sono deprecati. Normalizzali usando pattern come `Foo::bar` o `[Class::class, 'method']`.

### Interpolazione di stringhe

L'interpolazione di stringhe con la sintassi `"${var}"` / `"${expr}"` è deprecata; usa `"{$var}"` o la concatenazione esplicita.

### Altro

* **`utf8_encode` / `utf8_decode`**: deprecate (utilizza al loro posto `mb_convert_encoding` o `iconv`).

---

<a id="common-mistakes"></a>
## ⚠️ Errori comuni

Ecco alcuni degli errori tipici riscontrati nell'uso delle novità di PHP 8.2:

### 1. Creazione di proprietà dinamiche
In PHP 8.2, l'assegnazione di un valore a una proprietà non dichiarata in una classe genera un avviso di deprecazione e produrrà un Fatal Error a partire da PHP 9.0.

```php
// app/Services/UserService.php
// ERRATO: genera un avviso di deprecazione in PHP 8.2
class UserService {
    public string $name;
}

$service = new UserService();
$service->email = 'user@example.com'; // Deprecation Warning: Creation of dynamic property is deprecated
```

### 2. Uso della sintassi deprecata di interpolazione di stringhe
La vecchia sintassi `${var}` è deprecata in PHP 8.2.

```php
// app/Services/NotificationService.php
// ERRATO: genera un avviso di deprecazione
$name = 'Alice';
echo "Hello ${name}"; // Deprecation Warning

// CORRETTO: usa la sintassi standard con le parentesi graffe
echo "Hello {$name}";
```

### 3. Ereditarietà con classi Readonly
Una classe `readonly` può estendere esclusivamente un'altra classe `readonly`.

```php
// app/DTO/Point3D.php
class Point2D {}

// ERRATO: Fatal Error: Readonly class Point3D cannot extend non-readonly class Point2D
readonly class Point3D extends Point2D {}
```

---

<a id="self-test-quiz"></a>
## Quiz di autovalutazione

Metti alla prova la tua comprensione delle novità di PHP 8.2.

### Domanda 1: Cosa succede quando definisci una classe come `readonly` in PHP 8.2?
* A) Tutte le sue proprietà vengono contrassegnate automaticamente come `readonly`, ma non è necessario definirne il tipo.
* B) Non è possibile aggiungere proprietà dinamiche alla classe e tutte le proprietà devono essere tipizzate.
* C) La classe può estendere una qualsiasi classe normale, ma le classi normali non possono estendere lei.

<details>
<summary>Clicca per vedere la risposta</summary>

**Risposta: B**  
Dichiarare una classe come `readonly` implica che tutte le sue proprietà sono implicitamente readonly e devono dichiarare un tipo. Inoltre, le classi readonly non possono avere proprietà dinamiche e possono ereditare solo da altre classi readonly.
</details>

### Domanda 2: Quale sintassi di interpolazione genera un avviso di deprecazione in PHP 8.2?
* A) `"Hello {$name}"`
* B) `"Hello ${name}"`
* C) `"Hello " . $name`

<details>
<summary>Clicca per vedere la risposta</summary>

**Risposta: B**  
L'interpolazione di stringhe nella forma `${var}` è deprecata in PHP 8.2 e genera un avviso di deprecazione. Si raccomanda di utilizzare invece la forma `{$var}`.
</details>

---

## Riassunto

PHP 8.2 indirizza il linguaggio in modo deciso verso la precisione dei tipi e la sicurezza strutturale. Introducendo le classi readonly e i tipi DNF (Forma Normale Disgiuntiva), gli sviluppatori ottengono un controllo dettagliato sull'immutabilità degli oggetti e sulle definizioni di tipi complessi.