Auf dem Weg zu Symfony 5

Symfony 4.3 kommt bald: Die geplanten neuen Features im Blick
Keine Kommentare

In Kürze erscheint die neue Minor-Version von Symfony. Sie läutet den Auftakt für Symfony 5 ein, das im November zeitgleich mit Version 4.4 erscheinen wird. Neben den großen neuen Features, wie der Mailer- und HTTP-Client-Komponente, werden auch bestehende Komponenten erweitert und verbessert sowie Deprecations eingeführt, die mit Symfony 5 abgeschafft werden. Hier sind die Wichtigsten dieser Neuerungen im Überblick.

Symfony 4.3 wird das vorletzte Minor-Release im 4.x-Zweig von Symfony. Im November erscheinen zeitgleich Version 4.4 und 5.0. Beide Releases haben den gleichen Feature-Umfang und unterscheiden sich lediglich darin, dass in Symfony 5 alle Deprecations entfernt werden, die sich in der vorherigen Major-Version angesammelt haben. Darüber hinaus wird Version 4.4 das nächste Long Term Support Release (LTS), dass die Version 3.4 ablösen wird. Die bisherigen Neuerungen bilden also eine wesentliche Grundlage für kommende Features in Symfony 5. Im Folgenden möchte ich die wichtigsten Neuerungen kurz umreißen. Im Fokus stehen dabei drei Bereiche: Was wird entfernt? Was wurde verändert? Was ist neu?

Symfony 4.3: Was wird entfernt?

Symfony hat ein klar ausformuliertes Backward-Compatibility-Versprechen. Damit wird sichergestellt, dass ein Upgrade innerhalb der aktuellen Major-Version keine bestehenden Features in einer Art verändert, dass sich erwartetes Verhalten ändert und zu Fehlern führt. Eine Ausnahme bilden sicherheitsrelevante Anpassungen. Das heißt, ein Upgrade von 4.2 auf 4.3 sollte mit sehr geringen Anpassungen möglich sein und man erhält lediglich im Deprecation Log einen Hinweis, wenn man sich auf „veraltetes“ Verhalten verlässt. Um ein späteres Upgrade auf Version 5 zu vereinfachen, sollte man sich über diese Deprecations informieren und sie im Rahmen der regulären Wartungsarbeit abbauen. Eine vollständige Auflistung der Deprecations wird immer in den UPGRADE-Notes gepflegt und enthält häufig auch Beispiele, wie die Änderung aussehen kann.

Eine der wichtigsten Deprecations in Symfony 4.3 ist die Handhabung von verschiedenen Typen in Umgebungsvariablen. Bisher war es möglich z. B. Integer- oder Float-Werte als Defaults für Umgebungsvariablen zu hinterlegen. In Zukunft müssen alle Umgebungsvariablen als String definiert werden (siehe Listing 1), da das System diese Werte ebenfalls als String übergibt und so Fehler bei der Verarbeitung vermieden werden.

parameters: # vorher:
    env(NAME): 1.5 # Deprecation-Warnung

parameters: # nachher:
    env(NAME): '1.5' # Der Wert muss explizit als String deklariert werden

Die Signatur der dispatch()-Methode im EventDispatcher wurde verändert, um sich dem vor kurzem etablierten PSR-14-Standard anzugleichen. Während vorher zwei Argumente benötigt wurden, der Name des Events und das Event-Objekt, dass an die Observer übergeben wird, ist in Zukunft nur noch das Event-Objekt verpflichtend und der Name optional. Das führt dazu, dass die Reihenfolge der Parameter vertauscht wird. Mit Symfony 4.3 können beide Varianten verwendet werden, aber erstere löst eine Deprecation-Warnung aus und wird mit Symfony 5 komplett abgeschafft. Um die alte Logik weiterverwenden zu können, muss der EventDispatcher durch LegacyEventDispatcherProxy::decorate($dispatcher) dekoriert werden. Eine weitere Änderung im Rahmen der EventDispatcher-Komponente, ist die Event-Klasse, die bisher immer als Grundlage, auch für eigene Events, verwendet werden musste. Statt der Event-Basisklasse aus der Komponente sollte in Zukunft Symfony\Contracts\EventDispatcher\Event verwendet werden. Der wesentliche Unterschied ist, dass die neue Klasse das StoppableEventInterface aus dem PSR-Standard implementiert und somit erlaubt, die Events mit jedem PSR-14-kompatiblen Dispatcher zu verwenden. Die Anpassungen im EventDispatcher haben auch eine Umbenennung der Symfony-eigenen Events zur Folge, was die Arbeit mit Symfonys Event Cycle spürbar vereinfacht, da der Klassenname an die Event-Bezeichnung angepasst wurde (Tabelle 1).

Event-Bezeichnung alter Klassennamen neuer Klassenname
kernel.request GetResponseEvent RequestEvent
kernel.controller FilterControllerEvent ControllerEvent
kernel.view GetResponseForControllerEvent ViewEvent
kernel.response FilterResponseEvent ResponseEvent
kernel.terminate PostResponseEvent TerminateEvent
kernel.exception GetResponseForExceptionEvent ExceptionEvent

Tabelle 1: Umbenennung der Event-Klassen in Symfony 4.3

In Symfony 4.2 wurde ein neues CacheInterface eingeführt, dass von den PSR-6- und PSR-16-Standards abweicht. Grund dafür war das Cache Stampede Protection-Feature, dass zu diesen Standards inkompatibel ist. Mit dem aktuellen Release wird das dadurch entstandene Wirrwarr an verschiedenen Cache-Adaptern ein wenig aufgeräumt. Der SimpleCacheAdapter sowie der Psr16Adapter werden als deprecated markiert. Auch die zugehörigen PSR-16-Adapter wurden als deprecated markiert. Stattdessen sollten entweder Psr16Cache oder das neue CacheInterface aus den Contracts verwendet werden. Das hat auch Anpassungen in der Framework-Konfiguration zur Folge. Statt auf das SimpleCacheInterface bzw. dessen Service-ID cache.app.simple sollte nun cache.app bzw. das CacheInterface verwendet werden, wenn Services einen Cache als Argument benötigen.

Die Security-Komponente hat einige Deprecations, die insbesondere bei der Verwendung von Rollen und eigenen Token-Klassen genau analysiert werden sollten. In der Vergangenheit wurde bereits das AdvancedUserInterface als deprecated markiert und nun hat es auch das Role und SwitchUserRole erwischt. Ersteres scheint auf den ersten Blick gravierender als es ist. Symfony unterstützt bereits String-basierte Benutzerrollen z. B. in UserInterface::getRoles(). In aktuelleren Symfony-Anwendungen sollte diese Klasse daher bereits eine untergeordnete Rolle spielen. Zukünftig wird sie auch intern nicht mehr benötigt. Entwickler, die die Security-Komponente dahingehend erweitert haben, können in dem entsprechenden Pull Request #22048 ansehen, wie die Nutzung zurückgebaut werden kann. Bei der Ablösung von SwitchUserRole sieht es etwas anders aus. Hier müssen alle Referenzen auf diese Rolle durch eine Prüfung auf das SwitchUserToken ersetzt werden. Im gleichen Zug wurden auch diverse Methoden mit Bezug auf Rollen angepasst, um die Änderung zu reflektieren. Beispielsweise wurde getRoles() im TokenInterface zu getRoleNames() umbenannt. Eine weitere wichtige Änderung im TokenInterface ist die (De-) Serialisierung. In Zukunft müssen die PHP-eigenen magischen Methoden verwendet werden und die entsprechenden Methoden serialize() bzw. deserialize() werden abgeschafft.

Darüber hinaus gibt es noch weitere Deprecations, z. B. im Bereich der Workflow-Komponente, der HttpFoundation sowie bei Formularen. Die Unterstützung mehrerer Template-Engines, die in der Realität nur selten benutzt wurde, wird auch abgeschafft. Damit hat sich Twig als De-facto-Standard für Templates in Symfony endgültig durchgesetzt und Symfony wird ab Version 5 keine eigenen PHP-Templates und Themes für Forms mehr bereitstellen. Spätestens vor einem Upgrade zu Symfony 5 sollte man sich auch diese Änderungen genau ansehen und die Deprecation Logs der betriebenen Anwendungen im Auge behalten, um sicher zu gehen, dass der Umstieg ohne größere Komplikationen möglich ist.

Was ändert sich?

Neben den Deprecations haben zahlreiche existierende Komponenten Anpassungen und Erweiterungen erfahren. Die Validation-Komponente wird mit 4.3 um jede Menge neue Constraints erweitert. Die beiden neuen Iban und Bic-Constraints helfen bei der Validierung von Zahlungsangaben nach dem ISO 9362-Standard. Der existierende CardScheme-Constraint wurde um den Typ UATP (Universal Air Travel Plan) erweitert, der insbesondere für Anwendungen mit Zahlungen im Hotel- und Reisegewerbe interessant sein kann. Mit dem Unique-Constraint wurde eine Möglichkeit geschaffen auf Eindeutigkeit eines Eintrags in einer Liste zu prüfen – Nicht zu verwechseln mit dem bereits existierenden UniqueEntity-Constraint, das sicherstellt, dass ein Datenbankfeld, z. B. die E-Mail-Adresse einer Benutzerin, eindeutig ist. Mit dem NotCompromisedPassword-Constraint kann man Passworteingaben absichern, indem das gehashte Passwort an einen Webservice übermittelt wird, um zu prüfen, ob es in einer Liste von bekannten, kompromittierten Passwörtern auftaucht. Dazu wird die API von haveibeenpwned.com verwendet und es ist eine der ersten Verwendungen der neuen HttpClient-Komponente, die im nächsten Abschnitt vorgestellt wird.

Im Bereich der Datums-Validierung wurde das Timezone-Constraint hinzugefügt. Es überprüft, ob es sich bei einer Eingabe um eine gültige Timezone-Angabe für PHP handelt, also beispielsweise Europe/Berlin. Über Optionen kann der Gültigkeitsbereich weiter eingeschränkt werden, z. B. auf Zeitzonen für eine bestimmte geographische Region. Für die Validierung von Zahlen gibt es vier zusätzliche Constraints: Positive, PositiveOrZero, Negative, NegativeOrZero. Das NotBlank-Constraint hat außerdem eine neue Option allowNull spendiert bekommen. Es ist standardmäßig auf false gesetzt ist, um das bekannte Verhalten zu replizieren. Um sicher gehen zu können, dass Werte als JSON serialisiert werden können, gibt es nun auch ein eigenes Json-Constraint, das ein json_decode() ausführt und anschließend in json_last_error() auf Fehler überprüft.

Neben der Validierung gibt es auch einige Verbesserungen in der Form-Komponente. Ein Feature, dass sich häufig gewünscht wurde, ist die Möglichkeit Form-Elementen einen Hilfetext zu spendieren, der HTML-Code enthalten kann. Dafür gibt es nun eine zusätzliche Option help_html, der man einen booleschen Wert übergeben kann, siehe erstes Beispiel in Listing 2. Außerdem wurden DateTimeType und DateType um die Option input_format erweitert, mit der man nun das Datumsformat als gültiges PHP-Format angeben kann, siehe zweites Beispiel in Listing 2.

$builder->add('accept_agb', CheckboxType::class, [
        'mapped' => false,
        'help' => '<a href="…">Ich habe die AGB gelesen.</a>',
        'help_html' => true,
    ]);

$builder->add('starts_at', DateTimeType::class, [
    'input' => 'string',
    'input_format' => 'm-d H:i',
]);

Symfonys DomCrawler findet vor allem in Functional Tests und bei dem in Symfony 4.2 vorgestellten neuen Testing-Tool Panther eine entscheidende Rolle. Durch die Integration der HTML5-PHP-Bibliothek werden einige Probleme und Inkonsistenzen mit HTML5-Elementen bei der Verwendung von PHPs DOM-Erweiterung ausgeglichen. Die Bibliothek hat sich bereits in anderen Projekten wie Drupal bewährt und wird nun optional auch im DomCrawler eingesetzt, wenn sie per Composer im Projekt installiert wurde. Darüber hinaus hat die Komponente einige neue Features bekommen. Den beiden Methoden html() und text(), die den Inhalt des aktuellen Elements ausgeben, kann nun zusätzlich ein Standardwert übergeben werden, der statt einer Exception zurückgegeben wird, wenn das Element leer ist. Das ermöglicht es fehlschlagende Tests aussagekräftiger zu machen, anstatt eine generische „The current node list is empty“-Meldung zu bekommen. Mit dem neuen WebTestAssertionTrait stellt Symfony außerdem eine umfangreiche Sammlung an Assertions bereit, die in Funktionalen Tests verwendet werden können. Der Trait wird im WebTestCase bereitgestellt und kann so nach einem Update sofort benutzt werden.

International PHP Conference

Entwickler – das verlorene Handbuch

by Stefan Priebsch (thePHP.cc)

My browser does what?

by Joel Lord (Red Hat OpenShift


Im Routing gibt es diverse Verbesserungen, die den Komfort erhöhen. Dazu gehört, dass der Debug-Befehl auch Bedingungen anzeigt, die für eine Route erfüllt sein müssen. Die Handhabung der condition-Option wurde ebenfalls erweitert. Neben Ausdrücken können nun auch boolesche Parameter übergeben werden. Einige häufig verwendete Optionen wie utf8, locale und format, können nun außerdem direkt an der Route definiert werden und müssen nicht extra unter options angegeben werden. Insbesondere bei Routen, die per Annotationen oder XML konfiguriert werden, sorgt das für deutlich bessere Übersichtlichkeit.

Auch die Konfiguration von Services wurde weiter verbessert. Symfony bietet die Möglichkeit Services mit einem Schlagwort (Tag) zu versehen, um z. B. alle getaggten Services als Argumente an einen anderen Service übergeben zu können. Die Verwendung von getaggten Services hat sich in der Vergangenheit bereits deutlich vereinfacht. Während man früher Compiler Passes registrieren musste, können sie seit Symfony 4 über das Schlüsselwort !tagged in der YAML-Konfiguration als Argument an Services übergeben werden. In Symfony 4.3 kann man nun den Index dieser Service-Liste über verschiedene Attribute steuern. Insbesondere wenn man viele Services übergeben will, von denen vermutlich nur einer oder wenige tatsächlich benötigt werden, will man vermutlich lieber einen PSR-11-Container statt eines Iterators übergeben, da dieser Lazy Loading unterstützt. Dazu wurde das !tagged-Schlüsselwort in zwei Variationen aufgeteilt: tagged_iterator und tagged_locator. Die Verwendung von immutables, also Klassen, die nach der Instanziierung nicht mehr verändert werden, sondern lediglich eine neue Instanz mit den veränderten Werten zurückgeben, werden sich außerdem über die Unterstützung immutable setters in der Service-Konfiguration freuen.

Weitere Änderungen in bestehenden Komponenten, wie z. B. in den Messenger, Workflow und HttpCache-Komponenten, inklusive ausführlicher Beschreibungen der hier vorgestellten Änderungen, findet man auch im Symfony Blog in den New In Symfony-Beiträgen.

Was ist neu?

Symfony 4.3 enthält mit der Mailer– und HttpClient-Komponente zwei große Neuerungen. Erstere wurde bereits bei der SymfonyLive London im Oktober letzten Jahres das erste Mal angekündigt. Die Komponente ist der geistige Nachfolger der eigenständigen Swiftmailer-Bibliothek und bietet neben einer modernisierten Codebasis einige neue Features. Die bisher noch nicht erwähnte dritte neue Komponente Mime sorgt im Mailer für ein besseres Handling von Dateianhängen. Sie wird mit Symfony 4.3 auch in der HttpFoundation für Responses mit Binärdaten integriert. Die beiden für Anwender herausragenden Modernisierungen in der Mailer-Komponente sind außerdem das vereinfachte Templating von Nachrichten mit Twig sowie die Unterstützung von zusätzlichen Adaptern. Bei API-basierten Adaptern, beispielsweise für Mailgun, kommt die neue HttpClient-Komponente zum Tragen.

Die Emails, die mit der Mailer-Komponente verschickt werden, sind der Teil der Mime-Komponente und bieten einige Vorteile gegenüber einer Swift_Message. Durch das optimierte Datenmodell ist der resultierende Objektgraph deutlich kleiner und damit auch die Größe der serialisierten Email und der Speicherverbrauch. Das Anhängen und Einbetten von Bildern ist ebenfalls deutlich einfacher, da explizite Helfermethoden wie attach() oder embedFromPath() bereitgestellt werden. Letztere erlaubt es die eingebetteten Bilder in einer HTML-Mail zu referenzieren, wie das Beispiel in Listing 3 zeigt.

$email = new Email();
$email->from('denis.brumann@sensiolabs.de')
    ->to(new Address('info@sensiolabs.de'))
    ->subject('Dies ist ein Test')
    ->text('Das ist ein einfacher Text.')
    ->html('<b>Neues Logo: <img src="cid:logo.png"></b>')
    ->embedFromPath('images/neues_logo.png', 'logo.png');

Die Mime-Komponente enthält auch eine Erweiterung der Email-Klasse namens TemplatedEmail. Mit ihr lassen sich HTML-Emails aus einem Twig-Template erzeugen. Dazu übergibt man der htmlTemplate()-Methode den Dateinamen des Twig-Templates und bei Bedarf kann man der Methode context() ein Array mit Template-Variablen übergeben, wie man es bereits aus Symfony-Controllern kennt. Aus dem Twig-Template heraus hat man außerdem Zugriff auf das email-Objekt und kann so zusätzliche Attachments oder Embeds hinzufügen oder Adressaten und Betreff im Template weiterverwenden. Darüber hinaus gibt es einige Erweiterungen in Twig, die beim Erstellen von HTML-Emails helfen – vom inline_css-Filter bis hin zu einer Inky-Extension. Damit kann Foundation for Emails verwendet werden, ein CSS-Framework für responsive HTML-Emails.

Der Versand der Emails wird in der Mailer-Komponente gesteuert. Neben einem generischen SMTP-Transport sowie diverser anbieterspezifischer Varianten z. B. für Google oder Sendgrid, wie sie auch schon Swiftmailer unterstützte, werden auch HTTP- und API-basierte Versandmethoden unterstützt. Hinzu kommen spezielle Transports, die insbesondere beim Versand von mehreren E-Mails hilfreich sind, z. B. Failover oder RoundRobin. Da alle Transports mit der gleichen Schnittstelle angesprochen und die gleichen Mime-Messages verwendet werden, kann man nahtlos zwischen SMTP und API-Anbietern wechseln, indem man die entsprechenden Provider-DSNs anpasst. Möchte man E-Mails asynchron versenden, muss man lediglich den Mailer mit einem entsprechend konfigurierten MessageBus aus der Messenger-Komponente initialisieren.

Die HttpClient-Komponente ist ein wesentlicher Baustein, um den Versand von E-Mails per API zu unterstützen. Auch im neuen NotCompromisedPassword-Validierungsconstraint kommt sie bereits zum Einsatz. Im Gegensatz zu den meisten etablierten Bibliotheken wie Guzzle, ist sie von Grund auf darauf ausgelegt asynchron zu arbeiten. Verschickt man ein Request mit dem HttpClient, bekommt man eine Response zurück, die erst beim Aufruf der entsprechenden Methoden eine Anfrage an die API abschickt. Ruft man beispielsweise die getHeaders()-Methode auf, wird ein Stream erzeugt, der lediglich diese abgefragt und dann pausiert. Ruft man anschließend getContent() auf, wird das Lesen des Streams fortgesetzt, um auch den Response-Body zu laden. Das neu eingeführte HttpClientInterface bietet neben der request()-Methode, von der man die Responses bekommt, eine weitere Methode stream(). Der kann man eine Liste von Responses übergeben. Mit ihr lassen sich beliebig viele HTTP-Requests streamen und so die Ladezeiten bei mehreren Requests deutlich reduzieren. In seiner Präsentation der Komponente auf der SymfonyLive in Paris hat Nicolas Grekas ein Beispiel gezeigt, dass per HttpClient 379 Bilder zeitgleich innerhalb von 0,4s von einem CDN lädt.

Fazit

Symfony 4.3 wird ein umfangreiches Release mit zahlreichen Verbesserungen bei bestehenden Komponenten und drei neuen Komponenten. Die neue Symfony-Version ist auch für diejenigen interessant, die auf Long Term Support-Releases setzen da das kommende Release das Ende der aktuellen LTS-Version 3.4 einläutet. Vielleicht wird die ein oder andere selbstgeschriebene Lösung durch die Verbesserungen obsolet. Die neuen Komponenten zeigen, dass selbst etablierte Bibliotheken Verbesserungspotenzial haben. Sie bieten nicht nur kosmetische Änderungen durch modernisierten Code, der aktuellen Standards entspricht, sondern auch funktionalen Mehrwert durch bessere Unterstützung von Parallelisierung und erweiterten Funktionsumfang. Plant man ein Upgrade auf Version 5 kann man bereits mit dem aktuellen Release einige Deprecations abarbeiten, die den Umstieg leichter machen werden.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -