---
title: 'PHP 8.2: What’s New — Types, Readonly Classes, Security & Migration | DevSense'
description: 'Guide PHP 8.2 : classes en lecture seule, types autonomes null/false/true, types DNF, #[SensitiveParameter], extension Random, dépréciation des propriétés dynamiques.'
faq:
    - { question: "Qu'est-ce que les classes Readonly dans PHP 8.2 ?", answer: "Une classe readonly marque implicitement toutes ses propriétés comme étant en lecture seule. Toutes les propriétés doivent être typées et la classe ne supporte pas les propriétés dynamiques. Elle ne peut hériter que d'autres classes readonly." }
    - { question: "Comment l'attribut #[SensitiveParameter] améliore-t-il la sécurité des applications ?", answer: "L'attribut #[SensitiveParameter] masque les valeurs sensibles (comme les mots de passe, clés ou jetons) dans les traces d'appels (stack traces), empêchant ainsi leur fuite accidentelle dans les journaux ou les rapports d'erreurs." }
    - { question: "Qu'est-ce que la forme normale disjonctive (DNF) dans PHP 8.2 ?", answer: "La DNF permet de combiner les types d'union et d'intersection dans un format normalisé, comme `(Countable&Traversable)|null` pour les méthodes acceptant des structures complexes ou null." }
    - { question: 'Pourquoi les propriétés dynamiques sont-elles dépréciées dans PHP 8.2 ?', answer: 'Les propriétés dynamiques sont dépréciées pour éviter les bogues liés à des fautes de frappe dans les noms de propriétés. Les classes doivent déclarer leurs propriétés, utiliser `#[AllowDynamicProperties]` ou implémenter `__set()`/`__get()`.' }
published: '2026-05-31'
---
# PHP 8.2 : Fonctionnalités majeures

Notes de terrain pour les équipes migrant de PHP 8.1.x à 8.2.x : ajouts au langage, attributs orientés sécurité, gestion plus stricte des chaînes de caractères et dépréciations à corriger avant la prochaine étape.

## Table des matières
* [#[SensitiveParameter] et traces d'appels plus sécurisées](#sensitive-parameter)
* [Classes Readonly](#readonly-classes)
* [Types autonomes (`null`, `false`, `true`) et DNF](#standalone-types-dnf)
* [Constantes dans les traits & enums dans les expressions constantes](#traits-constants)
* [INI : `error_log_mode`](#error-log-mode)
* [Extension Random](#random-extension)
* [Mises à jour notables d'extensions (cURL, PCRE)](#extension-updates)
* [Changements non rétrocompatibles (notes de migration)](#backward-incompatible)
* [Dépréciations (à corriger avant qu'elles ne deviennent des erreurs)](#deprecations)
* [Notes sur les extensions & le runtime](#extensions-notes)
* [Erreurs courantes](#common-mistakes)
* [Quiz d'auto-évaluation](#self-test-quiz)

---

PHP 8.2 oriente fermement le langage vers la clarté des types et la sécurité structurelle. Avec l'introduction des classes readonly et des types en forme normale disjonctive (DNF), les développeurs obtiennent un contrôle granulaire sur l'immuabilité des objets et les déclarations de types complexes. La sécurité est également intégrée au niveau du langage, vous permettant de marquer explicitement les identifiants sensibles à l'aide de `#[SensitiveParameter]` afin d'éviter qu'ils ne fuitent dans les traces d'appels. Cependant, cette version introduit des dépréciations majeures—notamment les propriétés dynamiques—pour intercepter les bogues avant la production. Voici votre guide de transition vers PHP 8.2.

<a id="sensitive-parameter"></a>
## #[SensitiveParameter] et traces d'appels plus sécurisées

L'attribut `#[\SensitiveParameter]` marque les paramètres qui doivent être masqués dans les traces d'appels et les sorties de débogage, réduisant ainsi les fuites accidentelles d'identifiants dans les journaux et les pages d'erreurs.

> [!NOTE]
> **Le saviez-vous ?**
> L'attribut `#[SensitiveParameter]` fonctionne nativement avec la sortie par défaut des traces d'exceptions de PHP. Lorsque PHP génère une trace d'appels, il remplace la valeur du paramètre par un objet `SensitiveParameterValue`, masquant ainsi complètement la chaîne brute dans les journaux !

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

Associez cela à des pratiques rigoureuses de journalisation et n'affichez jamais d'exceptions brutes en production.

### Recette pratique : marquer les secrets aux frontières de l'application

Utilisez `#[\SensitiveParameter]` sur les paramètres susceptibles de se retrouver dans des exceptions (wrappers de clients, utilitaires d'authentification). Cela permet de conserver des traces utiles sans divulguer d'identifiants.

```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>
## Classes Readonly

Une classe peut être déclarée `readonly`, rendant **toutes** ses propriétés d'instance en lecture seule (readonly) et exigeant leur initialisation lors de la construction (ce qui équivaut à appliquer `readonly` à chaque propriété).

> [!NOTE]
> **Le saviez-vous ?**
> Une classe readonly empêche automatiquement les propriétés dynamiques ! Vous n'avez pas besoin d'utiliser l'attribut `#[AllowDynamicProperties]` car toute tentative d'ajout d'une propriété dynamique à una classe readonly lèvera immédiatement une Error.

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

Utilisez cette fonctionnalité pour les objets de valeur (value objects) immuables et les DTO où l'ensemble du graphe d'objets doit être figé après la construction.

---

<a id="standalone-types-dnf"></a>
## Types autonomes (`null`, `false`, `true`) et DNF

PHP 8.2 autorise **`null`**, **`false`** et **`true`** comme types autonomes dans les déclarations (et non plus uniquement comme membres d'un type d'union).

Les types **DNF (Disjunctive Normal Form / Forme Normale Disjonctive)** vous permettent de combiner des types d'**union** et d'**intersection** sous une forme normalisée, par exemple `(A&B)|null`—très utile pour concevoir des API précises sans perdre la possibilité d'accepter null.

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

---

<a id="traits-constants"></a>
## Constantes dans les traits & enums dans les expressions constantes

* **Constantes dans les traits** : elles sont désormais autorisées—pratique pour partager des configurations communes sans recourir à une classe de base supplémentaire.
* **Propriétés d'Enums dans des expressions constantes** : vous pouvez référencer des cas d'enums ou leurs propriétés là où des expressions constantes sont requises, autorisant ainsi des configurations plus riches à la compilation.

---

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

La directive INI **`error_log_mode`** définit les permissions de fichier pour le fichier de journalisation des erreurs (error log) lorsque PHP le crée—utile pour les déploiements sécurisés (par exemple, pour éviter des journaux lisibles par tous).

---

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

L'extension **Random** consolide et étend les API de génération de nombres aléatoires. Elle propose des choix de générateurs de nombres aléatoires (RNG) plus clairs et réduit les risques liés à l'utilisation isolée d'anciennes fonctions ad hoc. Privilégiez-la pour le nouveau code nécessitant des graines (seeds) reproductibles, de meilleurs algorithmes ou de la testabilité.

### Recette pratique : `Randomizer` pour les jetons et l'échantillonnage

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

Utilisez un moteur initialisé avec une graine (seeded engine) dans les tests pour rendre les résultats aléatoires déterministes et donc testables ; utilisez un moteur cryptographiquement sûr pour la génération de secrets.

---

<a id="extension-updates"></a>
## Mises à jour notables d'extensions (cURL, PCRE)

* **cURL** : `CURLINFO_EFFECTIVE_METHOD` expose la méthode HTTP effective ; `curl_upkeep()` aide à maintenir la connexion ; les constantes libcurl plus récentes sont exposées lorsqu'elles sont disponibles.
* **PCRE** : le modificateur **`n` (NO_AUTO_CAPTURE)** rend les groupes ordinaires `()` non capturants à moins qu'ils ne soient nommés—pratique pour les motifs complexes avec moins de références arrière numérotées.

---

<a id="backward-incompatible"></a>
## Changements non rétrocompatibles (notes de migration)

### Date & heure

* `DateTime::createFromImmutable()` / `DateTimeImmutable::createFromMutable()` utilisent désormais des types de retour **provisoirement `static`** (plus précis qu'auparavant pour les outils d'héritage).
* Formats de dates relatives : les symboles de nombres n'acceptent plus de signes multiples (par exemple, `+-2`).

### Bibliothèque standard (impact élevé)

* **Casse ASCII indépendante de la configuration locale** : `strtolower()`, `strtoupper()`, `lcfirst()`, `ucfirst()`, `ucwords()` et les appels associés ne sont **plus dépendants de la configuration locale (locale-sensitive)** ; ils se comportent comme la configuration locale `"C"`. Utilisez **mbstring** pour les conversions de casse localisées.
* **`str_split('')`** retourne désormais `[]` (auparavant `[""]`).
* **`glob()` / `GlobIterator`** : sous `open_basedir`, le comportement lors d'un tableau vide vs `false` ainsi que les avertissements ont changé—contrôlez l'analyse de répertoires dans les hébergements restreints.
* **`FilesystemIterator`** : `SKIP_DOTS` n'est plus forcé par défaut ; définissez explicitement les options si vous dépendiez de l'ancien comportement par défaut.
* **`ksort` / `krsort`** : `SORT_REGULAR` applique de manière cohérente les règles de chaînes numériques de PHP 8.
* **`var_export()`** : les barres obliques inverses initiales (backslashes) pour les noms de classes ne sont plus omises (noms pleinement qualifiés).

### ODBC / PDO_ODBC

Le nom d'utilisateur et le mot de passe sont désormais **échappés** lorsqu'ils sont ajoutés aux chaînes de connexion—cela corrige les injections et les chaînes mal formées ; vérifiez vos tests d'intégration avec de vrais DSN.

### SPL

Plusieurs méthodes de `SplFileObject` imposent désormais leurs signatures ; les types de retour de certaines méthodes ont été resserrés (`hasChildren`, `getChildren`).

---

<a id="deprecations"></a>
## Dépréciations (à corriger avant qu'elles ne deviennent des erreurs)

### Propriétés dynamiques

La création de **propriétés dynamiques** sur des classes quelconques est dépréciée, sauf si la classe utilise l'attribut **`#[\AllowDynamicProperties]`** (ou hérite de types comme `stdClass` qui l'autorisent). Privilégiez les propriétés déclarées, une `WeakMap` pour les métadonnées externes, ou les méthodes explicites `__get`/`__set`.

### Éléments appelables partiels (Partial callables)

Les callables uniquement acceptés par `call_user_func()` mais pas par la forme `$callable()`—comme `"self::method"`, `"parent::method"`, ou certaines formes de tableaux—sont dépréciés. Normalisez-les vers des structures de type `Foo::bar` ou `[Class::class, 'method']`.

### Interpolation de chaînes de caractères

L'interpolation de style `"${var}"` / `"${expr}"` est dépréciée ; utilisez `"{$var}"` ou une concaténation explicite.

### Divers

* **`utf8_encode` / `utf8_decode`** : dépréciées (utilisez `mb_convert_encoding` ou `iconv`).

---

<a id="common-mistakes"></a>
## ⚠️ Erreurs courantes

Voici quelques pièges courants lors de l'utilisation des fonctionnalités de PHP 8.2 :

### 1. Créer des propriétés dynamiques
Dans PHP 8.2, affecter une valeur à une propriété inexistante sur une classe déclenche un avertissement de dépréciation, et lèvera une erreur fatale dans PHP 9.0.

```php
// app/Services/UserService.php
// MAUVAIS : Déclenche un avertissement de dépréciation en 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. Utiliser la syntaxe d'interpolation de chaîne dépréciée
L'ancienne syntaxe `${var}` est dépréciée dans PHP 8.2.

```php
// app/Services/NotificationService.php
// MAUVAIS : Déclenche un avertissement de dépréciation
$name = 'Alice';
echo "Hello ${name}"; // Deprecation Warning

// BON : Utilisez la syntaxe d'accolades standard
echo "Hello {$name}";
```

### 3. Tenter de faire hériter une classe Readonly d'une classe classique
Une classe `readonly` ne peut hériter que d'une autre classe `readonly`.

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

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

---

<a id="self-test-quiz"></a>
## Quiz d'auto-évaluation

Testez votre compréhension des nouveautés de PHP 8.2.

### Question 1 : Que se passe-t-il lorsque vous définissez une classe comme `readonly` dans PHP 8.2 ?
* A) Toutes ses propriétés sont automatiquement marquées comme `readonly`, mais elles n'ont pas besoin d'être typées.
* B) Vous ne pouvez pas ajouter de propriétés dynamiques à la classe, et toutes les propriétés doivent être typées.
* C) Elle est autorisée à hériter de n'importe quelle classe classique, mais les classes classiques ne peuvent pas en hériter.

<details>
<summary>Afficher la réponse</summary>

**Réponse : B**  
Déclarer une classe comme `readonly` signifie que toutes ses propriétés sont implicitement readonly et doivent être typées. De plus, les classes readonly ne peuvent pas avoir de propriétés dynamiques, et elles ne peuvent hériter que d'autres classes readonly.
</details>

### Question 2 : Quelle syntaxe d'interpolation déclenche un avertissement de dépréciation dans PHP 8.2 ?
* A) `"Hello {$name}"`
* B) `"Hello ${name}"`
* C) `"Hello " . $name`

<details>
<summary>Afficher la réponse</summary>

**Réponse : B**  
Le style d'interpolation `${var}` est déprécié dans PHP 8.2 et déclenche un avertissement. Vous devez utiliser `{$var}` à la place.
</details>

---

## Résumé

PHP 8.2 oriente fermement le langage vers l'explicitation des types et la sécurité structurelle. En introduisant les classes readonly et les types DNF (Forme Normale Disjonctive), les développeurs obtiennent un contrôle précis sur l'immuabilité des objets et les types complexes.