Aller au contenu principal

PHP 8.2 : la consolidation du système de types et modernisation de l’API

Analyse détaillée de PHP 8.2 : classes readonly généralisées, types DNF pour unions et intersections, refonte de l'API Random, et fin des propriétés dynamiques avec exemples
Catégorie

PHP

Le PHP de 2025 n'a plus rien à voir avec celui d'il y a 10 ans. Êtes-vous sûr d'utiliser tout le potentiel des dernières versions pour écrire un code moderne et ultra-performant ?

Lecture
6 min
Niveau
Intermédiaire
janv 26 2026
Partager

PHP 8.2, publié en décembre 2022, poursuit l'évolution du langage amorcée avec la version 8.0. Cette itération se concentre sur le renforcement du typage, l'élimination de comportements hérités problématiques, et la modernisation d'API vieillissantes.

Le changement le plus visible concerne l'extension du mot-clé readonly introduit en 8.1. Alors que la version précédente permettait de déclarer des propriétés individuelles en lecture seule, 8.2 autorise désormais ce modificateur au niveau de la classe entière.

L'immutabilité simplifiée

Avant PHP 8.2, créer un objet totalement immutable nécessitait d'ajouter readonly devant chaque propriété :

PHP
// PHP 8.1
class Configuration {
    public function __construct(
        public readonly string $apiKey,
        public readonly string $endpoint,
        public readonly int $timeout,
        public readonly array $headers,
    ) {}
}

La nouvelle syntaxe applique cette contrainte à l'ensemble de la classe :

PHP
// PHP 8.2
readonly class Configuration {
    public function __construct(
        public string $apiKey,
        public string $endpoint,
        public int $timeout,
        public array $headers,
    ) {}
}

Cette approche s'avère particulièrement adaptée aux objets de transfert de données et aux value objects, où l'immutabilité constitue une garantie architecturale. Une classe déclarée readonly ne peut contenir aucune propriété modifiable, sans exception possible.

Types DNF : intersections et unions combinées

Le système de types de PHP s'enrichit progressivement. La version 8.0 a introduit les unions (A|B), la 8.1 les intersections (A&B). PHP 8.2 permet maintenant de les combiner selon une forme normale disjonctive (DNF) :

PHP
interface Serializable {
    public function serialize(): string;
}

interface Cacheable {
    public function getCacheKey(): string;
}

class Document {}
class Response {}

function process((Serializable&Cacheable)|Document|Response $item): void {
    // Accepte un objet implémentant Serializable ET Cacheable,
    // ou une instance de Document ou Response
}

Cette capacité répond à des besoins spécifiques dans les architectures complexes où plusieurs contrats alternatifs doivent être exprimés. L'utilisation reste néanmoins à manier avec précaution pour éviter des signatures devenues illisibles.

Précision accrue avec les types autonomes

PHP 8.2 introduit true, false et null comme types autonomes, permettant de décrire avec exactitude le comportement des fonctions :

PHP
// Pattern PHP classique : false indique une erreur
function findUser(int $id): User|false {
    $result = $db->query("SELECT * FROM users WHERE id = ?", [$id]);
    return $result ?: false;
}

// null indique explicitement l'absence de valeur
function getOptionalConfig(string $key): string|null {
    return $config[$key] ?? null;
}

// true pour les fonctions d'assertion qui réussissent ou lancent une exception
function assert(bool $condition, string $message = ''): true {
    if (!$condition) {
        throw new AssertionError($message);
    }
    return true;
}

Cette granularité s'avère précieuse pour documenter le comportement des fonctions legacy qui utilisent false comme valeur d'erreur, une convention répandue dans l'écosystème PHP. Le système de types peut désormais refléter fidèlement ces patterns sans approximation.

Refonte complète de la génération aléatoire

L'extension Random remplace l'ensemble des fonctions de génération aléatoire existantes par une API orientée objet cohérente :

PHP
$randomizer = new Random\Randomizer();

// Génération d'entiers
$number = $randomizer->getInt(1, 100);

// Génération de bytes
$bytes = $randomizer->getBytes(16);

// Mélange d'arrays
$shuffled = $randomizer->shuffleArray(['a', 'b', 'c']);

// Sélection aléatoire
$selected = $randomizer->pickArrayKeys($items, 3);

L'architecture permet d'injecter différents moteurs de génération selon les besoins :

PHP
// Génération reproductible pour les tests
$engine = new Random\Engine\Mt19937(seed: 12345);
$randomizer = new Random\Randomizer($engine);

// Génération cryptographiquement sûre
$secure = new Random\Engine\Secure();
$randomizer = new Random\Randomizer($secure);

Cette approche élimine les problèmes liés aux états globaux et facilite considérablement l'écriture de tests déterministes. Les développeurs disposent désormais d'un contrôle granulaire sur la génération aléatoire, une nécessité dans les environnements modernes.

Constantes dans les traits

PHP 8.2 autorise la déclaration de constantes dans les traits, comblant une limitation sans justification technique :

PHP
trait HttpClient {
    private const TIMEOUT = 30;
    private const USER_AGENT = 'PHP/8.2';
    
    protected function request(string $url): string {
        // Utilise les constantes définies dans le trait
    }
}

Cette fonctionnalité améliore l'encapsulation en permettant aux traits de définir leurs propres valeurs internes sans polluer les classes qui les utilisent.

Dépréciation des propriétés dynamiques

Le changement le plus controversé de PHP 8.2 concerne les propriétés dynamiques. Historiquement, PHP permettait d'ajouter des propriétés à n'importe quel objet à la volée :

PHP
class User {
    public string $name;
}

$user = new User();
$user->name = "Alice";
$user->email = "alice@example.com";  // Propriété non déclarée

Ce comportement, hérité des débuts du langage, a généré d'innombrables bugs silencieux liés à des fautes de frappe ou des erreurs de refactoring. PHP 8.2 émet désormais un avertissement de dépréciation lors de la création de propriétés dynamiques.

Les classes nécessitant ce comportement peuvent explicitement l'autoriser via l'attribut #[AllowDynamicProperties] :

PHP
#[AllowDynamicProperties]
class LegacyCache {
    // Autorise les propriétés dynamiques
}

Cette approche force les développeurs à déclarer explicitement leurs intentions tout en préservant la compatibilité avec le code existant. La dépréciation deviendra une erreur dans une future version majeure.

Le mot de la fin

PHP 8.2 marque une étape charnière dans la maturation du langage. Plus qu'une simple mise à jour incrémentale, cette version révèle une vision claire : transformer PHP en un langage typé moderne sans sacrifier son ADN pragmatique.

L'introduction des classes readonly, des types DNF et des types littéraux (true, false, null) témoigne d'une ambition : permettre aux développeurs d'exprimer leurs intentions avec précision tout en laissant le compilateur détecter les erreurs avant qu'elles n'atteignent la production. La refonte de l'extension Random et l'ajout des constantes dans les traits, quant à eux, démontrent une volonté d'éliminer les incohérences historiques qui minaient la crédibilité du langage.

Mais le signal le plus fort reste la dépréciation des propriétés dynamiques. En s'attaquant à ce comportement hérité des origines du langage, PHP rompt avec son passé permissif pour adopter une philosophie "fail-fast" où les erreurs de conception se manifestent explicitement plutôt que de se propager silencieusement.

Cette évolution n'est pas sans risque. Chaque dépréciation, chaque durcissement du système de types peut rebuter les développeurs attachés à la flexibilité historique de PHP. Pourtant, ces changements répondent aux exigences d'applications modernes de plus en plus complexes, où la maintenance et la fiabilité priment sur la tolérance aux erreurs.

PHP 8.2 ne révolutionne pas le langage. Il le raffine, l'épure, le renforce. C'est précisément cette approche pragmatique, équilibrant innovation et compatibilité, qui permet à PHP de rester pertinent dans un écosystème en perpétuelle mutation. Pour les équipes prêtes à adopter ces nouvelles pratiques, c'est l'opportunité de construire des applications plus robustes. Pour les autres, c'est un avertissement : le PHP permissif d'autrefois cède progressivement sa place à un langage qui assume ses choix et impose sa rigueur.

Poursuivre la lecture

Sélectionné avec soin pour vous.

DevOps

Docker et les containers : parce-qu'il faut expliquer avec des pancakes

Comprendre le multi-stage build, les healthchecks et l'isolation kernel via la métaphore des pancakes.

5 min de lecture
Symfony

PHP 8 et Symfony : la révolution discrète qui change tout

Fini les annotations et le YAML. Découvrez comment les attributs PHP 8 unifient la configuration de Symfony (routes, sécurité, Doctrine, DTOs) en exemples.

7 min de lecture
PHP

PHP 8.0 : la révolution qui a tout changé

Découvrez PHP 8.0 : JIT, arguments nommés, attributs, match expression, opérateur nullsafe et types d'union : tout ce qu'il faut savoir avec exemples pratiques.

8 min de lecture