Aller au contenu principal
Retour au blog

Symfony 8.2 en chantier : Cron, ObjectMapper et AutoconfigureTag en approche

Flavien Métivier15 août 202610 min

Symfony 8.1 est stable depuis fin mai 2026 — nous avions détaillé son basculement vers les applications HTTP-less et ses nouvelles commandes multi-méthodes dans un précédent article. Six mois plus tard, l'attention de l'équipe core est tout entière tournée vers la branche 8.2, dont la sortie est calée pour novembre 2026. Ce qui suit n'est pas une liste de nouveautés figées : c'est un instantané du chantier en cours, construit à partir des pull requests réellement fusionnées ces dernières semaines dans symfony/symfony. Tout peut encore bouger d'ici le gel des fonctionnalités — une API peut changer de forme, une feature peut glisser vers la 8.3 — mais suivre ce chantier permet de comprendre où va le framework, et parfois de remonter un bug avant qu'il ne soit figé dans une release stable.

Pourquoi suivre une branche de développement change la donne

Le calendrier Symfony est connu à l'avance : 8.1 en mai 2026, 8.2 en novembre 2026, 8.3 en mai 2027, puis 8.4 — la prochaine LTS — en novembre 2027. Entre deux releases mineures, six mois de développement s'écoulent avec un rythme de merge soutenu, documenté chaque semaine dans la série A Week of Symfony du blog officiel. Une équipe qui attend la release stable pour découvrir les changements se retrouve souvent à migrer dans l'urgence — c'est exactement l'écueil que nous avions documenté au moment du passage de la 7.4 LTS vers la série 8.x. Suivre les PR au fil de l'eau permet au contraire de tester un composant en -dev, de signaler un comportement surprenant pendant qu'il est encore modifiable, et d'arriver à la release stable sans surprise sur le CHANGELOG.

[Validator] Une contrainte Cron — logée là où on ne l'attend pas

Première précision qui a son importance : la nouvelle contrainte de validation d'expressions cron (PR #64538, mergée dans la branche 8.2 par ErfanMomeniii) n'est pas ajoutée au composant Scheduler, mais au composant Validator. La nuance compte : jusqu'ici, valider une chaîne cron saisie par un utilisateur — dans un formulaire d'administration de tâches planifiées, par exemple — obligeait à choisir entre une regex maison (qui laisse passer des expressions invalides) ou un parseur tiers enveloppé dans une callback Callback. La nouvelle contrainte Cron s'appuie en interne sur le même parseur que le composant Scheduler, mais elle s'utilise indépendamment de lui, sur n'importe quelle propriété de DTO ou d'entité.

  • MODE_STANDARD — expressions cron Vixie strictes à 5 champs, sans alias
  • MODE_ALIASES (mode par défaut) — le standard plus les alias @yearly, @monthly, @daily, @hourly, etc.
  • MODE_HASHED — le standard, les alias, et les formes hachées propres au Scheduler comme #midnight, prévisibles car dérivées du message
<?php
use Symfony\Component\Validator\Constraints as Assert;

class ScheduledTaskConfig
{
    #[Assert\Cron]
    public string $schedule; // accepte '0 3 * * *' ou '@daily'

    #[Assert\Cron(mode: Assert\Cron::MODE_STANDARD)]
    public string $strictSchedule; // refuse les alias, exige la forme à 5 champs
}

Le parseur gère les wildcards, les listes séparées par virgules, les plages, les steps (y compris les steps sur plage type 0-30/5) et les noms abrégés de mois et de jours, insensibles à la casse. Un seul code d'erreur est exposé, INVALID_FORMAT_ERROR, ce qui simplifie les tests. Aucune dépendance externe n'a été introduite — c'est du parsing PHP pur, ce qui explique pourquoi la PR atterrit dans Validator plutôt que dans un composant qui dépend déjà d'un cron parser tiers.

[ObjectMapper] Convertir des enums vers leurs valeurs scalaires sans code custom

Nous avions consacré un article entier au mapping de DTO natif avec ObjectMapper. La PR #62392 (mergée le 1er juillet 2026 sur la branche 8.2, contribuée par Nayte91) comble un manque récurrent dans ce workflow : jusqu'ici, convertir un backed enum vers sa valeur scalaire — ou l'inverse — obligeait à écrire deux classes de transformation, une pour chaque sens, et à les référencer explicitement via #[Map(transform: ...)] sur chaque propriété concernée. Le cas d'usage est fréquent avec Symfony Messenger : un message doit rester sérialisable (donc porter des scalaires), alors que l'entité métier manipule un enum typé.

<?php
// Avant la PR #62392 : un Transformer dédié par sens de conversion
final class CreatePostCommand // reçu du formulaire
{
    public function __construct(
        public ?string $content = null,
        public ?PostStatus $status = null, // backed enum : draft|published|archived
    ) {
    }
}

final class CreatePostMessage // envoyé au worker Messenger, doit être sérialisable
{
    public function __construct(
        public ?string $content = null,
        public ?string $status = null, // désormais mappé automatiquement, sans Transformer
    ) {
    }
}

ObjectMapper détecte désormais le type de la propriété cible et convertit automatiquement dans les deux sens, tant que la combinaison a un sens : un scalaire vers un enum du bon type de retour (int ou string), un backed enum vers son scalaire natif, et un enum vers lui-même sans changement de comportement. Toute autre combinaison continue de lever une exception plutôt que de produire une valeur silencieusement incorrecte — un choix cohérent avec la philosophie du composant, qui a toujours préféré échouer fort à deviner.

  • scalaire int → enum int-backed
  • scalaire string → enum string-backed
  • enum string-backed → scalaire string
  • enum int-backed → scalaire int
  • enum → le même enum, comportement inchangé

[ObjectMapper] Le correctif « N targets per source » : une leçon de méthode

En creusant le sujet ObjectMapper, une autre PR revient souvent dans les discussions autour de la 8.2 : la gestion de plusieurs classes cibles pour une même classe source lors du mapping inverse. Il faut être honnête sur sa nature exacte : la PR #64567 (« Handle N targets per source in reverse class map », soyuka) n'est pas une nouvelle fonctionnalité de la 8.2, mais un correctif de bug ciblant directement la branche 8.1 — elle sera donc livrée dans une version corrective (8.1.x) plutôt qu'à la sortie de la 8.2. Le bug lui-même est parlant : quand deux classes déclarent #[Map(source: SameSource::class)] vers la même source, seule la première gagnait le mapping inverse ; pour toute autre cible, la factory relisait les métadonnées de propriété de la gagnante, ignorant silencieusement les #[Map(transform:)] propres à la cible perdante — avec, en bout de chaîne, des valeurs fausses ou un TypeError sur une sous-propriété typée.

C'est un bon exemple de ce que suivre le développement permet de voir concrètement : une régression identifiée et corrigée en quelques semaines, avant qu'elle ne touche davantage de projets en production. Si votre équipe mappe déjà plusieurs DTO vers une même entité source avec ObjectMapper, c'est un correctif à surveiller sur votre prochain composer update, indépendamment de la sortie de la 8.2.

Besoin d'un expert Symfony ?

Réserver un appel →

[DependencyInjection] Calculer les attributs d'AutoconfigureTag par service taggé

La PR #64652 (nicolas-grekas, mergée le 3 juillet 2026 sur la branche 8.2) répare une régression de confort introduite par la dépréciation des méthodes defaultIndexMethod et defaultPriorityMethod sur les locators et itérateurs taggés (PR #62339). Cette dépréciation avait un effet de bord signalé dans l'issue #64407 : une interface qui exposait une méthode statique liait les clés — ou les priorités — du locator à un type analysable statiquement, ce qui permettait à PHPStan ou Psalm de détecter une faute de frappe dans une implémentation. En perdant cette méthode, on perdait cette garantie statique.

<?php
// PHP 8.5 : closure directement dans l'attribut
#[AutoconfigureTag('app.batch_handler', attributes: static function (string $class): array {
    return ['action' => $class::getSupportedBatchAction()];
})]
interface BatchHandlerInterface
{
    public static function getSupportedBatchAction(): string;
}

// Équivalent PHP 8.4 : callable [class-string, method], utilisable dès aujourd'hui
#[AutoconfigureTag('app.batch_handler', attributes: [self::class, 'getTagAttributes'])]
interface RefundHandlerInterface
{
    public static function getTagAttributes(): array;
}

L'attribut accepte donc désormais un callable qui reçoit la classe concrète du service taggé (en late static binding) et retourne le tableau d'attributs correspondant, calculé au moment de la compilation du container — dans ResolveInstanceofConditionalsPass — de sorte que rien n'atteint le container dumpé qui ne pourrait l'être. Les closures dans les attributs exigent PHP 8.5 ; la forme [class-string, method] fonctionne dès PHP 8.4 et reste même exprimable en YAML via _instanceof, ce qui restaure un vrai équivalent pour les équipes qui déclarent leurs services en configuration plutôt qu'en attributs.

[TypeInfo] Le support des templates covariants

Moins visible côté application, la PR #64130 (gsteel, squashée sur la branche 8.2) ajoute au composant TypeInfo la reconnaissance de @template-covariant et de ses variantes issues des outils d'analyse statique. Le résolveur de types ne le comprenait pas jusqu'ici, ce qui pouvait produire une résolution de type incorrecte sur des génériques covariants — typiquement une interface de collection en lecture seule dont le type de retour peut légitimement être une sous-classe du type déclaré. TypeInfo est le composant sur lequel s'appuient Serializer, PropertyInfo et ObjectMapper pour introspecter les types PHP ; une amélioration ici se propage silencieusement à tout ce qui en dépend, sans qu'aucun code applicatif n'ait à changer.

[Yaml] Des messages d'erreur qui disent enfin où chercher

La PR #64764 (eyupcanakman, mergée le 3 juillet 2026 sur la branche 8.2) referme un vieux ticket, l'issue #33082. Le symptôme : une chaîne quotée multi-lignes dont la ligne de continuation ou de fermeture est indentée en dessous du niveau où elle commence fait sortir la quote fermante du bloc de valeur — et le parseur échoue avec Malformed inline YAML string, un message qui ne donne aucune piste sur la cause réelle.

foo:
    bar: 'first line
        second line
'

Le nouveau message nomme le problème directement : « Unterminated quoted string. If it spans multiple lines, its continuation lines must be indented at least as deeply as where it starts. » Le comportement de parsing ne change pas — l'entrée reste invalide, un assouplissement avait été tenté puis annulé dans une PR antérieure — seul le diagnostic s'améliore. Cette PR ne vient pas seule : la même quinzaine a vu passer une restriction du parseur de blocs à la grammaire ASCII (PR #64631) et plusieurs corrections sur le parsing des ancres et des nombres. Le composant Yaml traverse une phase de durcissement méthodique avant la 8.2, ce qui est plutôt bon signe pour qui l'utilise en configuration critique.

Comment tester Symfony 8.2 dès aujourd'hui

Deux approches cohabitent selon le niveau d'engagement souhaité. Pour tester un comportement précis sans embarquer tout le framework en développement, on peut cibler un seul composant en version dev-8.2. Pour un projet applicatif complet, il vaut mieux isoler cet essai dans une branche dédiée et une CI spécifique, plutôt que de polluer la configuration Composer du projet principal.

# Teste uniquement le composant ObjectMapper en version dev
composer require symfony/object-mapper:8.2.x-dev --no-update
composer update symfony/object-mapper --with-all-dependencies

# Pour un projet applicatif complet (branche CI dédiée uniquement)
composer config minimum-stability dev
composer config prefer-stable false
composer require symfony/framework-bundle:8.2.x-dev

C'est exactement ce type de veille active — suivre les PR, isoler les tests de composants en dev, remonter les régressions avant qu'elles ne se figent — qui distingue une équipe qui subit ses montées de version d'une équipe qui les anticipe. Si votre stack Symfony a plusieurs années d'ancienneté, ou si personne en interne n'a le temps de suivre ce rythme de développement au quotidien, un audit technique ciblé permet de faire le point sur ce qui mérite d'être testé maintenant, ce qui peut attendre la 8.2 stable, et ce qui devrait être traité avant que la dette ne s'accumule.

Cet article vous a plu ? Partagez-le !

Besoin d'un expert Symfony ?

20 ans d'expérience sur l'écosystème PHP/Symfony.