SF
{ }
Symfony 7 · Migration · PHP 8.2 · Breaking Changes
Symfony 7: Was ist neu
und was fällt weg?

Symfony 7 ist die erste Major-Version seit Symfony 5, die PHP 8.2 als Mindestanforderung setzt und eine Reihe lange deprecateter APIs endgültig entfernt. Gleichzeitig bringt Symfony 7 echte Neuerungen: den ClockInterface-Standard, den AssetMapper als webpack-freie Alternative, überarbeitete DI-Attribute und einen deutlich schlankeren Core. Dieser Artikel zeigt, was konkret neu ist, was entfernt wurde und wie die Migration von 6.4 auf 7 aussieht.

18 Min. Lesezeit Neue Features · Breaking Changes · Migration · PHP 8.2+ Symfony 7.x · LTS 6.4 · PHP 8.2+

1. Symfony 7 im Überblick: Was hat sich grundlegend verändert?

Symfony 7 folgt dem bewährten Release-Zyklus: Symfony 6.4 ist die LTS-Version mit Security-Support bis 2027, Symfony 7 ist der neue Major-Release, der alle in 6.x als deprecated markierten APIs entfernt und gleichzeitig neue Funktionen einführt. Das Upgrade-Modell ist dasselbe wie bei jedem Symfony-Major: Erst auf 6.4 upgraden und alle Deprecation-Warnungen beheben, dann ist der Sprung auf Symfony 7 ohne Überraschungen. Projekte, die auf 6.4 sauber migriert sind, brauchen in der Regel nur die Composer-Constraints zu aktualisieren.

Das übergreifende Thema von Symfony 7 ist Reduktion und Klarheit: Weniger Bridge-Code für alte PHP-Versionen, weniger Abstraktionsschichten über veraltete Patterns, mehr native PHP-8-Features im Core. Das äußert sich in konkreten Zahlen: Etwa 50 Klassen und Interfaces, die in Symfony 6.x als deprecated markiert waren, wurden in Symfony 7 entfernt. Gleichzeitig wurden Klassen, die für PHP-8-Features wie Fibers, Enums und readonly Properties optimiert wurden, im Core verankert. Das Ergebnis ist ein Framework, das modernes PHP als Basis voraussetzt statt es als optionale Ergänzung zu behandeln.

2. PHP 8.2 als Mindestanforderung: Konkrete Auswirkungen

PHP 8.2 als Mindestanforderung bedeutet, dass Symfony 7 von mehreren PHP-8.2-Features abhängig ist: readonly Class Properties, Disjunctive Normal Form Types (DNF Types) und die strikte Typisierung für manche Framework-Klassen. Der praktische Effekt: Symfony-Core-Klassen können jetzt readonly auf Property-Deklarationen verwenden, ohne Setter-Methoden anbieten zu müssen. Das gilt insbesondere für Value-Objekte im Framework-Core wie SplFileInfo-Wrapper und Request-Attribute-Klassen.

Die PHP-8.2-Anforderung schließt implizit PHP-8.0 und 8.1 aus. Für Teams, die noch auf PHP 8.1 sind, ist Symfony 7 nicht verfügbar — sie müssen bei Symfony 6.4 bleiben. Der Upgrade-Pfad ist klar: PHP 8.2 upgraden, dann Symfony 6.4 migrieren, dann Symfony 7 upgraden. In der Praxis laufen die meisten gut gewarteten Symfony-Projekte bereits auf PHP 8.2 oder 8.3, weil PHPStan und andere Analyse-Tools für PHP 8.2+ bessere Unterstützung bieten. Für diese Projekte ist der Symfony 7-Upgrade der natürliche nächste Schritt nach einem erfolgreichen 6.4-LTS-Release-Wechsel.


<?php
// composer.json — minimum requirements for Symfony 7
// {
//   "require": {
//     "php": ">=8.2",
//     "symfony/framework-bundle": "^7.0"
//   }
// }

// PHP 8.2 readonly classes — now used in Symfony 7 core value objects
readonly class ProductId
{
    public function __construct(
        public readonly int $value,
    ) {}
}

// PHP 8.2 DNF types — used in Symfony 7 interfaces
function process((Countable&Traversable)|null $collection): void
{
    // DNF type: (Countable AND Traversable) OR null
}

// PHP 8.2 enum support — Symfony 7 uses enums for framework states
enum HttpMethod: string
{
    case GET    = 'GET';
    case POST   = 'POST';
    case PUT    = 'PUT';
    case PATCH  = 'PATCH';
    case DELETE = 'DELETE';
}

// Migration check: find all deprecated APIs in your project
// composer require --dev symfony/deprecation-contracts
// Run: php bin/console debug:container --deprecated
// Then: php bin/console lint:container (Symfony 7 pre-check)

3. Die Clock-Komponente: Testbarer Umgang mit Zeit

Die symfony/clock-Komponente ist eine der bedeutendsten Neuzugänge in Symfony 7. Sie löst ein fundamentales Testbarkeitsproblem: Code, der direkt new \DateTime(), time() oder Carbon::now() verwendet, ist nicht ohne Clock-Manipulation testbar. Die ClockInterface aus PSR-20 definiert eine einzige Methode now(): DateTimeImmutable. Die Symfony-Clock-Komponente liefert dazu drei Implementierungen: NativeClock für Produktion, MockClock für Tests und MonotonicClock für Zeitdifferenzmessungen.

Im Produktionscode injiziert man ClockInterface als Dependency anstelle von direkten new \DateTime()-Aufrufen. Symfony 7 bringt dazu den #[Autowire('@clock')]-Alias, der die NativeClock-Implementierung ohne explizite services.yaml-Konfiguration injiziert. In Tests ersetzt man die NativeClock durch eine MockClock, die auf eine feste Zeit gesetzt ist oder die man manuell vorrücken kann. Das ermöglicht deterministisches Testen von zeitabhängiger Geschäftslogik — Ablauf-Prüfungen, Scheduler-Logik, Zeitstempel-Berechnungen — ohne externe Libraries oder globale State-Manipulationen. Symfony 7 integriert ClockInterface tief in eigene Komponenten: Validator, Messenger und Cache nutzen intern bereits die Clock-Abstraktion.

4. AssetMapper: JavaScript ohne Node.js und Webpack

Der AssetMapper ist eine der meistdiskutierten Neuerungen, die Symfony 7 als Standard-Frontend-Lösung mitbringt. Er ersetzt Webpack Encore als empfohlene Asset-Pipeline für neue Symfony-Projekte und funktioniert ohne Node.js, ohne npm und ohne Build-Schritt. Der AssetMapper liest JavaScript-Files mit nativen ES-Modules-Imports, versieht sie mit Content-Hash für Cache-Busting und stellt sie direkt aus einem assets/-Verzeichnis bereit. In Produktion werden die Dateien über importmap-Tags eingebunden, die Browser nativ ESM-Imports auflösen können.

Die Kombination aus AssetMapper und Importmaps ermöglicht die Nutzung von npm-Packages direkt im Browser — ohne Bundle-Schritt. php bin/console importmap:require stimulus lädt Stimulus aus einem CDN und trägt es in die importmap.php ein. Beim nächsten Seitenaufruf ist das Package verfügbar. Für Projekte, die bereits Webpack Encore nutzen, bleibt Encore in Symfony 7 weiterhin unterstützt — AssetMapper ist die neue Standardempfehlung für Neuinstallationen über symfony new --webapp. TypeScript, CSS-Preprocessing und komplexe Build-Pipelines bleiben der Domäne von Webpack Encore oder Vite überlassen — der AssetMapper ist bewusst schlank gehalten.


<?php
// Symfony 7 Clock — injectable time abstraction for testable code

declare(strict_types=1);

namespace App\Service;

use Symfony\Component\Clock\ClockInterface;

/**
 * Subscription service — uses ClockInterface for testable expiry checks.
 */
final class SubscriptionService
{
    public function __construct(
        // Inject ClockInterface — NativeClock in production, MockClock in tests
        private readonly ClockInterface $clock,
        private readonly SubscriptionRepository $repository,
    ) {}

    /**
     * Check if a subscription is still active at the current time.
     */
    public function isActive(int $subscriptionId): bool
    {
        $subscription = $this->repository->find($subscriptionId);
        if (!$subscription) {
            return false;
        }

        // ClockInterface::now() returns DateTimeImmutable — fully testable
        return $subscription->getExpiresAt() > $this->clock->now();
    }

    /**
     * Extend subscription by 30 days from now.
     */
    public function extend(int $subscriptionId): void
    {
        $subscription = $this->repository->find($subscriptionId);

        // No direct new \DateTime() — deterministic in tests
        $newExpiry = $this->clock->now()->modify('+30 days');
        $subscription->setExpiresAt($newExpiry);

        $this->repository->save($subscription);
    }
}

// Test with MockClock — no global date manipulation needed
// $clock = new MockClock(new \DateTimeImmutable('2026-01-01 00:00:00'));
// $service = new SubscriptionService($clock, $repository);
// $clock->modify('+31 days'); // advance time to test expiry

5. Neue DI-Attribute: Autowire, AutowireIterator und mehr

In Symfony 7 wurden die Dependency-Injection-Attribute aus Symfony 6.x vollständig stabilisiert und um neue Optionen erweitert. #[Autowire(lazy: true)] erzeugt einen Lazy-Proxy für den injizierten Service — der Service wird erst beim ersten Methodenaufruf instanziiert, nicht beim Container-Aufbau. Das verbessert die Boot-Performance bei Services, die selten oder nur unter bestimmten Bedingungen genutzt werden. #[AutowireCallable] injiziert einen Service als Callable — nützlich für Factory-Pattern, bei denen der Service erst zur Laufzeit aus dem Container geholt werden soll.

#[Target] ist ein neues DI-Attribut in Symfony 7, das die Auflösung von tagged Services präziser steuert. Wenn mehrere Services dasselbe Interface implementieren, wählt #[Target('primary')] gezielt den als Primary markierten Service aus — ohne den Interface-Namen zu ändern oder manuelle services.yaml-Einträge zu schreiben. Das macht Multi-Implementierungs-Szenarien wie A/B-Testing von Service-Strategien oder Environment-spezifische Implementierungen deutlich sauberer. #[AsAlias] wurde ebenfalls gestärkt: Es akzeptiert jetzt mehrere Interface-IDs auf einer Klasse für Fälle, in denen ein Service unter verschiedenen Interface-Namen im Container veröffentlicht werden soll.

6. Was fällt weg: Entfernte Komponenten und Klassen

Symfony 7 entfernt alle in Symfony 5.x und 6.x als deprecated markierten APIs. Die wichtigsten Entfernungen betreffen: Das AnnotationReader-basierte System aus doctrine/annotations ist im Symfony-Core nicht mehr als Fallback vorhanden — native PHP-Attribute sind jetzt der einzige unterstützte Weg. Das AbstractController::getDoctrine()-Shortcut wurde entfernt — stattdessen direkt EntityManagerInterface oder ManagerRegistry injizieren. Die ContainerAwareInterface und ContainerAwareTrait wurden aus dem Framework-Bundle entfernt — Service-Locator-Pattern via ServiceSubscriberInterface ist der korrekte Ersatz.

Das sensio/framework-extra-bundle ist mit Symfony 7 endgültig überflüssig: @Template, @ParamConverter und @Cache hatten in Symfony 6.x bereits native Alternativen, die jetzt vollständig stabilisiert sind. Wer noch @ParamConverter nutzt, migriert auf #[MapEntity] (für Doctrine-Entities) oder auf Custom-Value-Resolver mit #[ValueResolver]. Das WebTestCase::createClient()-Verhalten wurde leicht verändert: Clients sind nun standardmäßig isolated, was Testinterferenzen durch geteilten State reduziert. Die Serializer-Komponente entfernte einige veraltete Normalizer-Interfaces und vereinheitlichte die Normalizer-Hierarchie.

7. HTTP-Kernel und Request-Mapping: Neue Möglichkeiten

Der HTTP-Kernel von Symfony 7 bringt verbesserte Unterstützung für das neue Request-Mapping über #[MapQueryString], #[MapRequestPayload] und #[MapUploadedFile]. Diese in Symfony 6.3 eingeführten Attribute sind in Symfony 7 vollständig stabil und als Standard-Pattern für Request-Handling dokumentiert. Der ArgumentResolver wurde intern refaktoriert, um den neuen Value-Resolver-Mechanismus effizienter zu machen: Die Resolver-Chain wird beim Container-Kompilieren aufgelöst, nicht beim Request-Handling — was in Hochlastszenarien zu weniger Overhead führt.

Das Attribut #[WithInput] kombiniert Symfony 7-intern MapQueryString und MapRequestPayload für Controller-Methoden, die sowohl Query-String als auch Body verarbeiten. Das Request-Objekt erhält in Symfony 7 neue Hilfsmethoden für die Arbeit mit Content-Negotiation und Accept-Headers — für APIs, die mehrere Formate unterstützen. Der EventDispatcher erhält Unterstützung für typed Events, die keine String-Namen mehr brauchen: Der Event-Typ ist der Identifier, was Typosicherheit in Event-Subscription garantiert. Das ist eine der kleineren, aber in der Praxis wichtigen Verbesserungen in Symfony 7.

8. Security-Verbesserungen in Symfony 7

Das Security-System von Symfony 7 erhält mehrere Verbesserungen im Bereich Authenticator und Token-Handling. Der AccessTokenAuthenticator wurde überarbeitet und unterstützt jetzt Bearer-Token-Authentifizierung für APIs out of the box — ohne zusätzliche Bundles. Die Konfiguration in security.yaml ist durch das neue access_token-Schlüsselwort direkt möglich. Symfony 7 verbessert auch den Passwort-Hasher: auto-Algorithmus wählt jetzt automatisch bcrypt, argon2i oder argon2id basierend auf den verfügbaren PHP-Extensions.

Das #[IsGranted]-Attribut erhält in Symfony 7 den Parameter exceptionCode, mit dem man den HTTP-Status-Code bei Access-Denied präzise steuern kann — 404 statt 403 für Security-through-Obscurity bei sensiblen Ressourcen. Der LoginThrottling-Mechanismus wird als Core-Feature stabilisiert: Mit einfacher Konfiguration in security.yaml limitiert Symfony 7 Login-Versuche pro IP und Benutzer ohne externe Rate-Limiting-Pakete. Diese Härtungsmaßnahmen sind besonders für öffentliche Anwendungen relevant und sparen externe Middleware-Konfiguration.

9. Symfony 6.4 vs. Symfony 7: Feature-Vergleich

Die Entscheidung zwischen Symfony 6.4 LTS und Symfony 7 hängt von Projektlaufzeit, Team-Größe und PHP-Version ab. Hier der direkte Vergleich der wichtigsten Punkte.

Merkmal Symfony 6.4 LTS Symfony 7 Empfehlung
PHP-Mindestversion PHP 8.1+ PHP 8.2+ Symfony 7 wenn PHP 8.2+ läuft
Security-Support bis 2027 (LTS) 2026 (standard) Langfristige Projekte: 6.4 oder 7.4 LTS
AssetMapper Backport aus 6.3 Stabil, Standard Neue Projekte: Symfony 7 + AssetMapper
Clock-Komponente Backport verfügbar Core-Integration Symfony 7 für tiefere Clock-Integration
doctrine/annotations Fallback vorhanden Entfernt — PHP Attribute Migration auf PHP Attribute vor Upgrade

Für bestehende Projekte auf Symfony 5.x oder 6.x ist der empfohlene Weg: Zuerst auf 6.4 upgraden, alle Deprecation-Warnungen beseitigen (insbesondere doctrine/annotations entfernen, getDoctrine() ersetzen, sensio/framework-extra-bundle deinstallieren), dann auf Symfony 7 upgraden. Dieser zweistufige Ansatz verhindert, dass Breaking Changes und Feature-Änderungen gleichzeitig debuggt werden müssen. Wer auf einem Clean-6.4-Stand ist, wird beim Symfony 7-Upgrade keine bösen Überraschungen erleben.

Mironsoft

Symfony-Migration, Upgrade-Beratung und PHP 8.2+ Modernisierung

Migration auf Symfony 7 planen und durchführen?

Wir analysieren euer bestehendes Symfony-Projekt auf Deprecations, erstellen einen strukturierten Migrationsplan und führen den Upgrade auf Symfony 7 mit PHP 8.2+ durch — ohne ungeplante Downtime und mit vollständigem Test-Coverage-Report.

Deprecation-Audit

Vollständige Analyse aller Symfony-Deprecations und Identifikation von Breaking-Change-Risiken

Migrations-Roadmap

Priorisierter Stufenplan: 6.4 LTS stabilisieren, dann Symfony 7 Upgrade ohne Überraschungen

Upgrade-Durchführung

Hands-on-Migration inkl. PHP 8.2+, PHPStan-Integration und vollständiger Testabdeckung

10. Zusammenfassung: Lohnt sich die Migration?

Symfony 7 ist für neue Projekte mit PHP 8.2+ die klare Empfehlung. Die Clock-Komponente, der stabilisierte AssetMapper, die vollständig nativen PHP-Attribute und der schlankere Core sind echte Verbesserungen, keine Marketing-Features. Für bestehende Projekte auf Symfony 6.4 LTS ist der Upgrade optional bis 2027 — wer gut gewarteten Code auf 6.4 hat, kann den Wechsel auf den nächsten LTS-Zyklus verschieben. Wer allerdings von Symfony 5.x oder älteren 6.x-Versionen kommt, sollte direkt den Weg über 6.4 nach Symfony 7 planen.

Die wichtigste Lektion aus vergangenen Symfony-Major-Releases gilt auch hier: Der Upgrade ist umso einfacher, je konsequenter Deprecation-Warnungen im laufenden Betrieb behoben wurden. Ein Projekt, das seit Jahren auf doctrine/annotations, sensio/framework-extra-bundle und getDoctrine()-Aufrufen aufbaut, braucht eine geordnete Migrationsstrategie. Ein Projekt, das seit Symfony 6.2 Deprecations konsequent behoben hat, ist in einem halben Arbeitstag auf Symfony 7.

Symfony 7: Was ist neu und was fällt weg — Das Wichtigste auf einen Blick

Neu in Symfony 7

PHP 8.2+ als Pflicht, Clock-Komponente (PSR-20), AssetMapper als Standard, stabilisierte DI-Attribute (#[Autowire(lazy:true)], #[Target]), AccessTokenAuthenticator.

Was fällt weg

doctrine/annotations-Fallback entfernt, getDoctrine()-Shortcut weg, sensio/framework-extra-bundle obsolet, ContainerAwareTrait entfernt, AbstractController-Shortcuts reduziert.

Migrations-Strategie

Erst auf Symfony 6.4 LTS migrieren, alle Deprecation-Warnungen beheben, dann Symfony 7 upgraden. PHP 8.2+ und Deprecation-freier Code sind Voraussetzung.

Entscheidungshilfe

Neue Projekte: Symfony 7. Langfristige Wartung: 6.4 LTS bis 2027. Migration: Zweistufig über 6.4, erst PHP upgraden, dann Symfony.

11. FAQ: Symfony 7 Neuerungen und Breaking Changes

1Was ist neu in Symfony 7?
PHP 8.2-Pflicht, Clock-Komponente (PSR-20), AssetMapper als Standard, verbesserte DI-Attribute (#[Target], lazy Autowire), AccessTokenAuthenticator für Bearer-Token-APIs.
2Was wurde entfernt?
doctrine/annotations-Fallback, getDoctrine(), sensio/framework-extra-bundle-Annotations, ContainerAwareTrait, ContainerAwareInterface — alle deprecated-APIs aus 5.x/6.x.
3PHP 8.2 zwingend?
Ja — Symfony 7 erfordert mindestens PHP 8.2. PHP 8.1-Projekte bleiben bei Symfony 6.4 LTS (Security-Support bis 2027).
4Was ist die Clock-Komponente?
PSR-20 ClockInterface — NativeClock für Produktion, MockClock für Tests. Ermöglicht deterministisches Testen zeitabhängiger Logik ohne globale State-Manipulation.
5Was ist der AssetMapper?
JavaScript ohne Node.js und npm — native ES-Modules mit Importmap. Standard für neue Symfony-7-Projekte. Webpack Encore bleibt für komplexe Build-Pipelines unterstützt.
6Migrationsweg von 6.4 auf 7?
1. PHP auf 8.2+ upgraden. 2. Alle Deprecations in 6.4 beheben. 3. Constraints in composer.json auf ^7.0 setzen und composer update ausführen.
7sensio/framework-extra-bundle noch nötig?
Nein. Alle Features haben native Alternativen: @Route → #[Route], @ParamConverter → #[MapEntity], @IsGranted → #[IsGranted], @Cache → #[Cache].
8Was ersetzt getDoctrine()?
EntityManagerInterface oder ManagerRegistry direkt im Konstruktor injizieren. getDoctrine() war Service-Locator-Pattern und wurde konsequent entfernt.
9Wann kommt Symfony 7 LTS?
Symfony 7.4 wird die LTS-Version mit Security-Support bis 2029. Erscheint Ende 2025. Langfristige Projekte sollten 6.4 LTS oder 7.4 LTS anvisieren.
10Funktionieren Symfony-6.x-Bundles in Symfony 7?
Meistens ja, wenn sie keine deprecated APIs nutzen. Aktiv gewartete Bundles haben Symfony-7-kompatible Releases. Bundles mit doctrine/annotations oder sensio-Abhängigkeiten müssen aktualisiert werden.