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.
Inhaltsverzeichnis
- 1. Symfony 7 im Überblick: Was hat sich grundlegend verändert?
- 2. PHP 8.2 als Mindestanforderung: Konkrete Auswirkungen
- 3. Die Clock-Komponente: Testbarer Umgang mit Zeit
- 4. AssetMapper: JavaScript ohne Node.js und Webpack
- 5. Neue DI-Attribute: Autowire, AutowireIterator und mehr
- 6. Was fällt weg: Entfernte Komponenten und Klassen
- 7. HTTP-Kernel und Request-Mapping: Neue Möglichkeiten
- 8. Security-Verbesserungen in Symfony 7
- 9. Symfony 6.4 vs. Symfony 7: Feature-Vergleich
- 10. Zusammenfassung: Lohnt sich die Migration?
- 11. FAQ
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.