Symfony 8, la nouvelle version majeure du framework PHP

28/11/2025
Pierre Gouedar Round

Pierre Gouedar

Symfony

Qu'est-ce que Symfony ?


Symfony est un framework PHP open-source destiné au développement web moderne. Il permet de créer des applications web performantes grâce à un ensemble de composants réutilisables et une architecture MVC modulaire. Symfony est reconnu pour sa robustesse, sa flexibilité et son écosystème riche comprenant des centaines de packages et bundles. Il est utilisé aussi bien pour des CMS que pour des architectures de plateformes à grande échelle.

Les nouveautés et améliorations de la version 8 de Symfony

Avec la version 8, Symfony intègre en profondeur les dernières avancées de PHP 8.4 et supprime toutes les dépréciations liées à la version 7.0. Cette mise à jour se concentre sur deux axes majeurs : enrichir l'expérience des développeurs et pousser les performances des applications à un niveau supérieur.

Exigence de PHP 8.4 minimum

La plus grosse nouveauté de Symfony 8 est son exigence de PHP 8.4 minimum pour fonctionner. Ce choix stratégique a été fait pour répondre à plusieurs objectifs :

Sécurité : Symfony veut s'assurer de fonctionner sur des versions de PHP les plus récentes, abandonnant ainsi les anciennes versions qui ne reçoivent plus de correctifs de sécurité.

Performances : Grâce à PHP 8.4, Symfony peut exploiter les dernières fonctionnalités liées aux gains de performance, comme les Lazy Objects qui permettent d'initialiser les services uniquement lorsqu'ils sont réellement utilisés.

<?php

use Symfony\Component\DependencyInjection\Attribute\Lazy;

#[Lazy]
class ExpensiveService
{
    private DatabaseConnection $connection;
    private ComplexCalculator $calculator;

    public function __construct(
        DatabaseConnection $connection,
        ComplexCalculator $calculator
    ) {
        // Initialisé uniquement quand le service est réellement utilisé
    }
}

Les commandes invocables (Invokable Commands)
    

L'une des fonctionnalités les plus attendues de Symfony 8 est la stabilisation des commandes invocables. Introduites dans Symfony 7.3 et enrichies dans la version 7.4, elles permettent de simplifier drastiquement l'écriture des commandes console.

Avant (approche classique)

<?php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

#[AsCommand(name: 'app:create-user')]
class CreateUserCommand extends Command
{
    protected function configure(): void
    {
        $this->addArgument('name', InputArgument::REQUIRED);
        $this->addOption('activate', null, InputOption::VALUE_NONE);
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $name = $input->getArgument('name');
        $activate = $input->getOption('activate');
        // ...
        return Command::SUCCESS;
    }
}

Après (approche invocable)

<?php 

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Attribute\Argument;
use Symfony\Component\Console\Attribute\Option;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand(name: 'app:create-user')]
class CreateUserCommand
{
    public function __invoke(
        SymfonyStyle $io,
        #[Argument] string $name,
        #[Option] bool $activate = false,
    ): int {
        // $name et $activate sont directement disponibles
        return Command::SUCCESS;
    }
}

Les principaux avantages sont :

  • Plus besoin d'hériter de la classe Command
  • Plus besoin de surcharger la méthode configure()
  • Les valeurs des arguments et options sont directement disponibles comme variables

Support des enums et DTOs

Symfony 8 améliore encore cette fonctionnalité avec le support des backed enums et l'attribut #[MapInput] pour les DTOs :

<?php 

enum CloudRegion: string
{
    case East = 'east';
    case West = 'west';
}

class AddServerInput
{
    #[Argument]
    public CloudRegion $region;
    
    #[Option]
    public ?int $size = null;
}

#[AsCommand('app:add-server')]
class AddServerCommand
{
    public function __invoke(
        OutputInterface $output,
        #[MapInput] AddServerInput $server,
    ): int {
        // Utilisation de $server->region et $server->size
        return Command::SUCCESS;
    }
}

Nouveaux composants stabilisés

Symfony 8 améliore plusieurs composants qui étaient expérimentaux dans la version 7.x :

TypeInfo

Le composant TypeInfo extrait les informations de type PHP depuis les propriétés, arguments et types de retour. Il gère les unions, intersections et génériques.

<?php

use Symfony\Component\TypeInfo\TypeResolver\TypeResolver;

class Dummy
{
    public function __construct(
        public int $id,
        /** @var string[] $tags */
        public array $tags,
    ) {
    }
}

$typeResolver = TypeResolver::create();
$typeResolver->resolve(new \ReflectionProperty(Dummy::class, 'id'));
// Retourne un type "int"

ObjectMapper

Le composant ObjectMapper simplifie la transformation d'objets, particulièrement utile pour mapper des DTOs vers des entités. Dans l'exemple ci-dessous, on définit un ProductInputDto qui sera automatiquement converti en entité Product grâce aux attributs #[Map] :

<?php 

use App\Entity\Product;
use Symfony\Component\ObjectMapper\Attribute\Map;

#[Map(target: Product::class)]
class ProductInputDto
{
    #[Map(target: 'name')]
    public string $productName;

    public string $description;

    #[Map(if: false)]
    public string $internalSku = '';

    #[Map(transform: 'floatval')]
    public string $price;
}

Utilisation dans un contrôleur :

<?php

#[Route('/product', name: 'product_create', methods: ['POST'])]
public function create(
    #[MapRequestPayload] ProductInputDto $productInput,
    ObjectMapperInterface $objectMapper,
    EntityManagerInterface $entityManager
): Response {
    $product = $objectMapper->map($productInput);
    $entityManager->persist($product);
    $entityManager->flush();

    return $this->json(['message' => 'Produit créé']);
}

JsonPath

Le composant JsonPath permet d'interroger et d'extraire des données JSON en utilisant des expressions, similaire à DomCrawler pour le HTML :

<?php 

use Symfony\Component\JsonPath\JsonCrawler;

$json = '{"store": {"books": [{"title": "Symfony Guide", "price": 29.99}]}}';
$crawler = new JsonCrawler($json);

$titles = $crawler->find('$.store.books[*].title');
// Filtre avancé
$cheapBooks = $crawler->find('$.store.books[?(@.price < 30)]');

JsonStreamer

Pour les APIs manipulant de gros volumes JSON, JsonStreamer offre un encodeur/décodeur streaming environ 10× plus rapide et 50-90% plus léger en mémoire que le Serializer :

<?php

use Symfony\Component\JsonStreamer\JsonStreamEncoder;

$encoder = new JsonStreamEncoder();
foreach ($encoder->encode($largeDataset) as $chunk) {
    echo $chunk;
}

Nouvelle configuration PHP avec tableaux

Symfony 8 abandonne les configurations XML et PHP fluent au profit des tableaux PHP. Un format compact et expressif avec autocomplétion et validation de types :

<?php

// config/packages/security.php
namespace Symfony\Component\DependencyInjection\Loader\Configurator;

return App::config([
    'security' => [
        'firewalls' => [
            'main' => [
                'pattern' => '^/*',
                'lazy' => true,
                'anonymous' => true,
            ],
        ],
        'access_control' => [
            ['path' => '^/admin', 'roles' => 'ROLE_ADMIN'],
        ],
    ]
]);

Pour ceux qui ne sont pas prêts, YAML reste disponible.

Gestion améliorée des dates sans fuseau horaire

Symfony 8 introduit un nouveau système pour gérer les dates "flottantes" — ces dates qui n'ont pas de fuseau horaire associé, comme une date de naissance ou une alarme quotidienne.

Le problème

PHP associait automatiquement un fuseau horaire à toutes les dates, ce qui créait des décalages inattendus. Une date de naissance comme "15 mai 1990" pouvait se transformer en "14 mai 1990 à 23h" selon le fuseau du serveur.

La solution

Symfony propose désormais trois types de points temporels :

<?php 

use Symfony\Component\Form\Extension\Core\Type\DateType;

// Pour une date (ex : 2025-10-29)
$builder->add('birthdate', DateType::class, [
    'input' => 'date_point',  // Utilise DayPoint
]);

// Pour une heure
$builder->add('alarm', TimeType::class, [
    'input' => 'date_point',  // Utilise TimePoint
]);

UuidV7 par défaut

Symfony 8 utilise maintenant UuidV7 par défaut pour les identifiants uniques. Cette version est plus précise, capable de gérer le temps à la microseconde tout en respectant la RFC 9562.

Pour les tests, un nouvel outil MockUuidFactory permet de fixer les UUID générés :

<?php 

use Symfony\Component\Uid\Factory\MockUuidFactory;

$factory = new MockUuidFactory('01912d08-2000-7000-8000-000000000001');
// Tous les UUID générés seront prévisibles pendant les tests

Améliorations des performances

Symfony 8 apporte des optimisations significatives :

  • Lazy Objects PHP 8.4 : Les services sont initialisés uniquement à l'utilisation
  • Compilation du conteneur optimisée : Plus de dépendances résolues au moment du build
  • Cache Twig amélioré : Chargement plus fluide des templates
  • Gestion des routes accélérée : Résolution plus rapide
  • Support natif de FrankenPHP : Un serveur PHP haute performance basé sur Go et Caddy
# docker-compose.yml avec FrankenPHP
services:
  app:
    image: dunglas/frankenphp:latest
    environment:
      FRANKENPHP_CONFIG: "worker ./bin/frankenphp-worker.php"

Définition des fonctions et filtres Twig avec attributs

Plus besoin d'étendre une classe de base pour créer des extensions Twig. Les fonctions et filtres sont désormais définis avec des attributs et chargés en lazy-loading :

<?php 

use Twig\Attribute\AsTwigFilter;
use Twig\Attribute\AsTwigFunction;

class AppExtension
{
    #[AsTwigFilter('product_number')]
    public function formatProductNumber(string $number): string
    {
        return 'PRD-' . strtoupper($number);
    }

    #[AsTwigFunction('current_user')]
    public function getCurrentUser(): ?User
    {
        // ...
    }
}

Nouvelles contraintes de validation

Symfony 8 enrichit son système de validation avec de nouvelles contraintes intégrées :

  • Validation de charsets
  • Validation d'adresses MAC
  • Validation de numéros de semaine ISO
  • Comptage de mots
  • Validation de syntaxe YAML
  • Validation de slugs
  • Validation de syntaxe Twig
  • Validation de fichiers vidéo

Récapitulatif des différences entre Symfony 8 et 7.4

Fonctionnalité Symfony 7.4 Symfony 8.0
Version PHP minimum PHP 8.2 PHP 8.4
Dépréciations Contient toutes les dépréciations 7.x Aucune dépréciation
Support LTS (bugs: Nov 2028, sécurité: Nov 2029) Regular (bugs et sécurité: Juil 2026)
Commandes invocables Disponibles Stabilisées et améliorées
TypeInfo, ObjectMapper, JsonPath Expérimentaux Stabilisés
Configuration XML, YAML, PHP fluent Tableaux PHP (+ YAML)
Lazy Objects Non disponible Support natif PHP 8.4
UuidV7 Optionnel Par défaut
Code source Inclut les couches de dépréciation 13 202 lignes supprimées

Quelle version choisir ?

Symfony 7.4 LTS est recommandé si :

  • Vous avez besoin d'un support long terme (4 ans de bugs, 5 ans de sécurité)
  • Vous ne pouvez pas migrer immédiatement vers PHP 8.4
  • Vous utilisez des bundles qui n'ont pas encore été mis à jour

Symfony 8.0 est recommandé si :

  • Vous pouvez utiliser PHP 8.4
  • Vous souhaitez bénéficier des dernières fonctionnalités
  • Vous préférez corriger les dépréciations progressivement entre versions mineures
  • Vous êtes un early adopter ou une startup avec une forte pression d'innovation

La recommandation officielle de Symfony est d'utiliser les versions régulières chaque fois que possible.

Conclusion

Pour ses 20 ans, Symfony 8 est une version qui marque le coup. Ce n'est pas juste une série de petites améliorations mais d'innovations majeures. Entre les commandes invocables qui transforment notre manière de coder, et l'intégration de composants comme ObjectMapper et JsonPath, cette nouvelle version va permettre aux développeur un gain de temps. Sans oublier les performances améliorées grâce à l'optimisation pour PHP 8.4. Un autre atout de Symfony 8 est l'adoption des attributs PHP natifs qui permet de dire adieu au boilerplate. Le code est devenu plus propre, plus lisible, et sa maintenance est un jeu d'enfant. En clair, pour quiconque veut bâtir des applications PHP modernes et solides, maîtriser Symfony 8 n'est plus une option, il s'agit de la marche à suivre.

Ressources et Documentation


Pierre Gouedar Round

Pierre Gouedar

Partager l'article

Partager sur linkedinPartager sur facebook

Pour aller plus loin...

Coolify Docs 2026 01 23 09 10
Développement web
Coolify : reprendre le contrôle de votre hébergement sans devenir expert DevOps

Coolify : réduisez vos coûts cloud de 70 % avec cette alternative open source à Vercel. Déploiement simple, données souveraines. Guide complet pour DSI/CTO.

Lire l'article

Vous souhaitez être accompagné pour lancer votre projet digital ?

Koul Logo Blanc Sans Fond
4 Rue Maurice Prevost, 51450 Béthenycontact@koul.io
BlogInstagramFacebookLinkedin
À propos
Qui sommes-nous ?L'histoireNos projetsNous contacter
KOUL 2026
Mentions légalesCGV