Aller au contenu principal
Illustration de l'article : Garder sa stack API Platform à jour : Retour d'expérience sur une migration PHP 8.5
24 Nov 2025
PHP FrankenPHP Symfony API Platform

Introduction

Dans le monde du développement web, maintenir sa stack technique à jour est essentiel pour bénéficier des dernières optimisations, fonctionnalités et correctifs de sécurité. Aujourd'hui, je partage mon expérience de migration d'une API Platform vers PHP 8.5, fraîchement sorti le 20 novembre 2025.

La stack avant/après

Voici un aperçu des composants mis à jour :

  • PHP : 8.4 → 8.5
  • Elasticsearch : 9.2.0 → 9.2.1
  • Redis Stack : latest → 7.4.0-v2
  • Mercure : v0 → v0.21.2
  • Doctrine ORM : 3.0 → 3.5
  • Symfony : 7.3 (en attente de la 8 !)

Les nouvelles fonctionnalités PHP 8.5 exploitées

1. Le Pipe Operator (|>)

L'une des fonctionnalités les plus attendues de PHP 8.5 est le pipe operator. Après trois tentatives de RFC, il est enfin là !

Avant PHP 8.5 :

$normalized = strtolower(trim($email));

Avec PHP 8.5 :

$normalized = $email |> trim(...) |> strtolower(...);

Le code se lit maintenant de gauche à droite, comme un flux de transformations. C'est particulièrement élégant pour les Value Objects :

class Email
{
    public function __construct(string $email)
    {
        $normalized = $email |> trim(...) |> strtolower(...);

        if (!filter_var($normalized, FILTER_VALIDATE_EMAIL)) {
            throw new \InvalidArgumentException('Email invalide');
        }

        $this->value = $normalized;
    }
}

2. L'attribut #[NoDiscard]

PHP 8.5 introduit l'attribut #[NoDiscard] qui émet un avertissement si la valeur de retour d'une fonction est ignorée. Parfait pour les factory methods !

#[\NoDiscard]
public static function create(string $auth0Id, Email $email): self
{
    $user = new self();
    $user->auth0Identifier = $auth0Id;
    $user->email = $email;

    return $user;
}

// ⚠️ Warning si on écrit :
User::create('auth0|123', $email); // Valeur ignorée !

// ✅ OK :
$user = User::create('auth0|123', $email);

J'ai ajouté cet attribut sur plus de 20 factory methods, ce qui aide à prévenir les bugs silencieux.

3. Public Readonly Properties

Avec PHP 8.4+, les Value Objects deviennent encore plus concis grâce aux propriétés publiques en lecture seule :

Avant :

final readonly class Dimensions
{
    public function __construct(
        private int $width,
        private int $height
    ) {}

    public function getWidth(): int
    {
        return $this->width;
    }

    public function getHeight(): int
    {
        return $this->height;
    }
}

Après :

final readonly class Dimensions
{
    public function __construct(
        public int $width,
        public int $height
    ) {}

    // Accès direct : $dimensions->width
}

Résultat : -30 lignes de code, accès plus direct, même immutabilité !

Optimisations avancées

Lazy Loading pour les services coûteux

Certains services comme Elasticsearch créent des connexions lourdes. Le lazy loading permet de ne créer ces ressources qu'à la première utilisation :

class ElasticsearchClientService
{
    private ?Client $client = null;

    public function __construct(
        private readonly string $hosts,
        private readonly LoggerInterface $logger
    ) {
        // Client NON créé ici - démarrage ultra-rapide
    }

    public function getClient(): Client
    {
        // Création uniquement à la première utilisation
        return $this->client ??= ClientBuilder::create()
            ->setHosts(explode(',', $this->hosts))
            ->build();
    }
}

Static Cache pour les enums

Les enums PHP ne peuvent pas avoir de propriétés, mais on peut utiliser des variables statiques dans les méthodes pour cacher des résultats :

enum LinkType: string
{
    case YOUTUBE = 'youtube';
    case VIMEO = 'vimeo';
    // ...

    public function isEmbeddable(): bool
    {
        static $cache = null;
        $cache ??= [
            self::YOUTUBE,
            self::VIMEO,
            self::SOUNDCLOUD,
        ];

        return in_array($this, $cache, true);
    }
}

Le tableau est créé une seule fois puis réutilisé à chaque appel.

Pièges à éviter

1. Xdebug pas encore compatible

Xdebug ne supporte pas encore PHP 8.5. Il faut le retirer temporairement de votre Dockerfile et attendre une version compatible.

2. Les enums ne peuvent pas avoir de propriétés

// ❌ Erreur fatale
enum Status
{
    private static array $cache = []; // INTERDIT !
}

// ✅ Solution
enum Status
{
    public static function getCache(): array
    {
        static $cache = null;
        return $cache ??= [...];
    }
}

3. Syntaxe du pipe operator

Attention à la syntaxe : on utilise ... pour la partial application, pas $ :

// ❌ ERREUR
$result = $value |> trim($) |> strtolower($);

// ✅ CORRECT
$result = $value |> trim(...) |> strtolower(...);

Résultats

Après cette migration complète, les gains sont significatifs :

  • 35+ fichiers optimisés
  • -30 lignes de code (getters supprimés)
  • 20+ factory methods sécurisés avec #[NoDiscard]
  • Démarrage plus rapide grâce au lazy loading
  • Code plus lisible avec le pipe operator

Conclusion

Migrer vers PHP 8.5 et mettre à jour l'ensemble de sa stack demande du temps, mais les bénéfices sont réels : code plus moderne, performances améliorées, et nouvelles fonctionnalités qui simplifient le quotidien.

Le pipe operator seul justifie la migration : fini les imbrications illisibles, place à un code qui se lit comme on le pense !

Conseil : Prenez le temps d'auditer votre code après la migration. Profitez-en pour appliquer les nouveaux patterns PHP 8.5 là où c'est pertinent. Votre code n'en sera que meilleur.


Manuel Grosrenaud
Manuel Grosrenaud
Fondateur / Associé