Aller au contenu principal

PHP 8.1 : l’expression après la révolution

Analyse détaillée de PHP 8.1 : enums avec méthodes, immutabilité simplifiée, infrastructure async avec Fibers, et système de types enrichi: tout ce qu'il faut savoir avec exemples pratiques.
Catégorie

Symfony AI

Lecture
8 min
Niveau
Intermédiaire
janv 25 2026
Partager

Un an après PHP 8.0, l'équipe derrière PHP aurait pu se reposer sur ses lauriers. Au lieu de ça, PHP 8.1 est arrivé en novembre 2021 avec une approche différente : plutôt que des changements spectaculaires, une série d'améliorations qui rendent le code plus sûr, plus expressif et plus élégant.

Enums

Pendant des années, nous avons bidouillé des pseudo-enums avec des constantes de classe. C'était moche, fragile, et ça ne profitait d'aucune vérification de type.

PHP
// L'ancienne méthode
class Status {
    const DRAFT = 'draft';
    const PUBLISHED = 'published';
    const ARCHIVED = 'archived';
}

function updatePost(string $status) {
    // Rien n'empêche de passer "banana"
}

Le problème ? N'importe quelle chaîne de caractères passait. Votre IDE ne vous aidait pas, le système de types ne vérifiait rien, et vous découvriez les erreurs en production.

PHP 8.1 a introduit de vraies énumérations natives, comme dans tous les langages modernes qui se respectent.

PHP
enum Status: string {
    case Draft = 'draft';
    case Published = 'published';
    case Archived = 'archived';
}

function updatePost(Status $status) {
    // Le système de types garantit que c'est une valeur valide
}

updatePost(Status::Published); // OK
updatePost('published'); // Erreur de type

Mais les enums en PHP ne sont pas de simples constantes déguisées. Ce sont des objets à part entière qui peuvent avoir des méthodes, implémenter des interfaces, et même contenir de la logique métier.

PHP
enum Status: string {
    case Draft = 'draft';
    case Published = 'published';
    case Archived = 'archived';
    
    public function color(): string {
        return match($this) {
            Status::Draft => 'gray',
            Status::Published => 'green',
            Status::Archived => 'red',
        };
    }
    
    public function canEdit(): bool {
        return $this === Status::Draft;
    }
}

$status = Status::Published;
echo $status->color(); // 'green'

C'est le genre de fonctionnalité qui semble évidente une fois qu'on l'a, et qui rend le code tellement plus robuste qu'on se demande comment on a pu s'en passer pendant 25 ans.

Propriétés Readonly

L'immutabilité, c'est bien en théorie. Tout le monde vous dit que c'est une bonne pratique. Mais en pratique, en PHP, ça voulait dire écrire des getters sans setters, marquer vos propriétés comme privées, et espérer très fort que personne ne modifie directement les valeurs.

Les propriétés readonly règlent ça définitivement.

PHP
class User {
    public function __construct(
        public readonly string $email,
        public readonly DateTime $createdAt,
    ) {}
}

$user = new User('john@example.com', new DateTime());
echo $user->email; // OK

$user->email = 'autre@example.com'; // Fatal error

Une propriété readonly ne peut être assignée qu'une seule fois, dans le constructeur. Combiné avec la promotion de propriétés de constructeur introduite dans PHP 8.0, ça devient remarquablement concis :

PHP
class Point {
    public function __construct(
        public readonly float $x,
        public readonly float $y,
    ) {}
}

Quatre lignes. Deux propriétés immutables, publiques, typées, avec un constructeur automatique. Aucun boilerplate superflu.

Fibers

Voilà quelque chose dont vous n'aurez peut-être jamais besoin directement, mais qui change absolument tout sous le capot : les Fibers. C'est l'infrastructure de bas niveau pour gérer de la concurrence légère en PHP.

Avant les Fibers, faire de l'asynchrone en PHP était compliqué. Les frameworks comme ReactPHP et Amphp avaient trouvé des solutions ingénieuses mais complexes, utilisant des generators et des callbacks imbriqués. Les Fibers permettent désormais de suspendre et reprendre l'exécution du code de manière beaucoup plus propre :

PHP
$fiber = new Fiber(function (): void {
    echo "Début de l'exécution\n";
    Fiber::suspend();
    echo "Fin de l'exécution\n";
});

$fiber->start(); // Affiche "Début de l'exécution"
// Le code principal continue ici...
$fiber->resume(); // Affiche "Fin de l'exécution"

La plupart d'entre nous n'utiliserons jamais les Fibers directement, et c'est parfait comme ça. Les frameworks asynchrones les utilisent pour offrir une syntaxe beaucoup plus naturelle, beaucoup plus proche du code synchrone classique. C'est le genre de fonctionnalité qui travaille en coulisses pour améliorer votre expérience sans que vous ayez à y penser.

Les Fibers sont la fondation sur laquelle se construit le futur asynchrone de PHP. Ils ne sont peut-être pas spectaculaires, mais ils sont essentiels.

Syntaxe Callable

Créer une référence à une méthode en PHP était embarrassant. Vous aviez le choix entre des strings magiques ou des arrays bizarres :

PHP
// Approches anciennes
$callable = 'strlen';
$callable = [$object, 'methode'];
$callable = [MaClasse::class, 'methodeStatique'];

Aucune vérification de type, aucune autocomplétion dans l'IDE. Une faute de frappe dans le nom de la méthode ? Vous ne le découvriez qu'à l'exécution, probablement en production.

PHP 8.1 introduit la syntaxe (...) pour créer des callables de première classe :

PHP
// Nouvelle syntaxe
$callable = strlen(...);
$callable = $object->methode(...);
$callable = MaClasse::methodeStatique(...);

// Utilisable directement
array_map($object->transformer(...), $data);
array_filter($items, $this->estValide(...));

Votre IDE comprend ce que vous faites e tle code est compréhensible. Quelqu'un qui lit votre code comprend immédiatement l'intention.

Types d'intersection

PHP 8.0 a introduit les types d'union (int|string), permettant de dire "ceci OU cela". PHP 8.1 complète le tableau avec les types d'intersection, pour dire "ceci ET cela" :

PHP
interface Loggable {
    public function log(): void;
}

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

function process(Loggable&Cacheable $item): void {
    $key = $item->getCacheKey();
    $item->log();
    // Le type garantit que l'objet implémente les deux interfaces
}

C'est particulièrement utile pour les patterns de composition, où vous voulez garantir qu'un objet implémente plusieurs contrats simultanément. Plus de vérifications manuelles, plus de instanceof en cascade. Le système de types fait le travail pour vous.

PHP
interface Jsonable {
    public function toJson(): string;
}

interface Timestamped {
    public function getTimestamp(): int;
}

function archive(Jsonable&Timestamped $record): void {
    $data = $record->toJson();
    $time = $record->getTimestamp();
    // Stockage avec timestamp...
}

Les types d'intersection permettent d'exprimer des contraintes complexes de manière élégante et sûre, sans complexifier le système de types.

Type de retour never

Certaines fonctions ne retournent jamais. Elles lancent une exception, appellent exit(), ou entrent dans une boucle infinie. Avant PHP 8.1, il n'y avait aucun moyen d'exprimer ça dans le système de types. Vous mettiez void, mais ce n'était pas vraiment correct : void signifie "retourne sans valeur", pas "ne retourne jamais".

PHP
// Avant
function redirect(string $url): void {
    header("Location: $url");
    exit;
}

// PHP 8.1
function redirect(string $url): never {
    header("Location: $url");
    exit;
}

function fail(string $message): never {
    throw new Exception($message);
}

Le type never indique explicitement que la fonction ne termine jamais normalement. Elle peut lancer une exception, elle peut terminer le script, mais elle ne retournera jamais au code appelant. C’est peut-être un détail pour vous, mais pour les outils d’analyse statique, ça veut dire beaucoup.

PHP
function verifyAge(int $age): void {
    if ($age < 18) {
        fail("Accès refusé");
        // Pas besoin de return ici
    }
    
    grantAccess(); // L'analyseur sait qu'on arrive ici seulement si age >= 18
}

Le mot de la fin

PHP 8.1 n'a pas eu le côté spectaculaire de PHP 8.0. Pas de compilateur JIT révolutionnaire promettant des gains de performance à deux chiffres. Pas de refonte syntaxique majeure forçant tout le monde à réapprendre le langage. Pas de breaking changes massifs qui font pleurer les mainteneurs de code legacy.

Mais ce qu'elle a apporté est tout aussi important : de la précision, de la nuance et de l'élégance.

Les enums ont donné un moyen propre et sûr d'exprimer des ensembles de valeurs fermés. Les propriétés readonly ont rendu l'immutabilité triviale au lieu d'être un combat constant. Les Fibers ont posé les fondations pour un futur asynchrone plus naturel. Les callables de première classe ont éliminé des années de syntaxe bancale. Les types d'intersection et never ont enrichi le système de types avec des nuances que les développeurs réclamaient depuis longtemps.

C'est une release qui ne crie pas ses améliorations sur tous les toits, mais qui les intègre dans chaque ligne de code que vous écrivez. Chaque fois que vous créez un enum au lieu de bidouiller des constantes. Chaque fois que vous marquez une propriété readonly au lieu d'implémenter un getter. Chaque fois que vous utilisez (...) au lieu de jongler avec des strings magiques.

Et parfois, c'est exactement ce dont un langage mature a besoin. Pas une autre révolution. Juste du raffinement, de la précision, de l'attention aux détails qui rendent la vie quotidienne meilleure.

PHP 8.1 est la preuve qu'un langage peut évoluer sans faire de bruit. Et que les meilleures améliorations sont celles qui deviennent tellement naturelles qu'on oublie comment on faisait avant.

Poursuivre la lecture

Sélectionné avec soin pour vous.

Symfony

PHP 8.4 Property Hooks : quand Doctrine 3.4 révolutionne vos Getters/Setters

Découvrez les Property Hooks PHP 8.4 avec Doctrine 3.4. Fini les getters/setters verbeux !

4 min de lecture
DevOps

Comment FrankenPHP a relégué PHP-FPM et Nginx au stade de reliques

Stop à Nginx + PHP-FPM. Découvrez pourquoi FrankenPHP est la solution moderne pour un setup Docker simple et performant.

13 min de lecture
PHP

Composer : le manifeste du développeur moderne

Découvrez comment composer.json est l'équivalent développeur d'un buffet à volonté, avec humour piquant et ironie sur les dépendances PHP.

5 min de lecture