PHP 8 ist da! Das Major Update wurde am 26. November 2020 veröffentlicht und bringt uns einige grundlegende Änderungen sowie viele neue Features. In welchem Fall PHP 8 wirklich zu einer besseren Performance führt und ob du als WordPress User:in bereits auf die neue Version updaten solltest, erklärt dir unser Entwickler Marten.
Einführung in PHP 8
PHP 8 wurde seinen Alpha-Tester:innen erstmals am 18. Juni 2020 vorgestellt und befand sich seit Juli in einem Feature Freeze. Bis zur Veröffentlichung am 26. November durften also keine neuen Ergänzungen mehr hinzugefügt werden. Eine Besonderheit dieser Version ist, dass wir PHP 7.5 überspringen und direkt zu PHP 8 übergehen. Und dieser Sprung ist mit einer Vielzahl von Features verbunden.
Eine der häufigsten Fragen zu PHP 8, die sich WordPress Nutzer:innen stellen ist vermutlich: Wird PHP 8 die Performance meiner Website verbessern?
Die Antwort auf diese Frage ist (wie so oft): “Es kommt darauf an…”
Als PHP von Version 5 auf Version 7 aktualisiert wurde, gab es einen enormen Performance Boost. Mit PHP 8 wirst du jedoch keine allgemeine Leistungsverbesserung feststellen, es sei denn, deine Anwendung berechnet viele mathematische Funktionen (siehe unseren Abschnitt über den JIT-Compiler). Dies liegt hauptsächlich daran, dass die Code Optimierung von PHP bereits sehr gut etabliert ist.
Aber wer sagt überhaupt, dass die Performance auf die Kompilierzeit beschränkt ist? Ich für meinen Teil würde als Entwickler die Leistung auf verschiedene Weise messen, einschließlich der Funktionen, die mir zur Verfügung stehen, um gut strukturierten Code zu schreiben. Und PHP 8 ist voller neuer Goodies. Also, lass uns loslegen!
Feature Updates in PHP 8
PHP 8 hat acht neue Hauptfeatures, die ich dir kurz vorstellen möchte:
- Der JIT Compiler
- Attributes
- Named Arguments
- Match Expressions
- Throw Expressions
- Static Return Type
- Union Type
- Mixed Types
Der JIT (just-in-time) Compiler (rfc)
Wenn PHP Code ausgeführt wird, geschieht dies normalerweise durch Kompilieren zu virtuellen Anweisungen, die auf einer virtuellen Maschine ausgeführt werden. JIT wird dies ändern, indem es den Code in x86-Maschinencode kompiliert und diesen Code dann direkt auf der CPU ausführt. Bei Anwendungen, die sich stark auf mathematische Funktionen stützen, sollte das zu einer Performancesteigerung führen. Bei durchschnittlichen Webanwendung ist dies allerdings nicht zu erwarten (siehe Grafik).
Für ein Beispiel für die Leistungssteigerung, die durch JIT erzielt werden kann, schau dir am besten das folgende Video an.
Im Grunde läuft es darauf hinaus, dass deine Anwendung mit der neuen Version reibungsloser läuft, wenn du PHP für einen arbeitsintensiven, mathematischen Task verwendest. Aber wenn du PHP wie die meisten WordPress User:innen nutzt, dann wirst keine großen Veränderungen feststellen. Mehr darüber, was PHP 8 für Betreiber:innen von WordPress Websites bedeutet, erkläre ich weiter unten.
Weiter geht’s mit den neuen Features:
Attributes v2 (rfc, rfc)
Eine der Neuerungen in PHP 8 (die in der PHP Community zu ausgiebigen Diskussionen geführt hat) sind Attributes – in vielen anderen Sprachen als “Annotations” bekannt. Attributes ersetzen in PHP 8 das Hinterlegen von Metadaten mit Docblocks. Darauf musstest du bisher zurückgreifen, um Metadaten für Klassen, Methoden, Funktionen und Argumente auf strukturierte Weise zu deklarieren.
Wie du dir vorstellen kannst, war die Verwendung von Code-Kommentaren zur Anwendung von Metadaten nicht ideal, aber es hat funktioniert. Glücklicherweise werden wir dieses Problem jetzt nicht mehr haben.
Attributes können mit der Syntax #[...]
deklariert werden.
Hier sind einige Beispiele aus dem RFC, wie Attributes auf verschiedene Datentypen angewendet werden können.
#[ExampleAttribute]
class Foo
{
#[ExampleAttribute]
public const FOO = 'foo';
#[ExampleAttribute]
public $x;
#[ExampleAttribute]
public function foo(#[ExampleAttribute] $bar) { }
}
$object = new #[ExampleAttribute] class () { };
#[ExampleAttribute]
function f1() { }
$f2 = #[ExampleAttribute] function () { };
$f3 = #[ExampleAttribute] fn () => 1;
An dieser Stelle ist es erwähnenswert, dass der RFC für Attributes seit seiner ursprünglichen Konzeption einige Änderungen erfahren hat, was den Aufwand und die Überlegungen zeigt, die in diese Aktualisierung gesteckt wurden.
Named Arguments (rfc)
Named Arguments ermöglichen dir mehr Flexibilität beim Aufruf von Funktionen. Bislang musstest du eine Funktion aufrufen und jedes Argument in der Reihenfolge übergeben, wie sie von der Funktion vorgegeben wurde.
// Using positional arguments:
array_fill(0, 100, 50);
Mit Named Arguments kannst du einen Namen für jeden Parameter definieren. Und jetzt können diese, wie unten beschrieben, außer der Reihenfolge aufgerufen werden:
// Using named arguments:
array_fill(start_index: 0, num: 100, value: 50);
Sie können außerdem folgendermaßen aufgerufen werden:
array_fill(value: 50, num: 100, start_index: 0);
Es ist auch ein Hybrid aus beiden möglich, der es erlaubt, benannte Parameter und Positionsargumente zu kombinieren, wodurch die Lesbarkeit des Codes verbessert wird:
htmlspecialchars($string, double_encode: false);
Match Expressions (rfc)
Match Expressions sollen einige, seit langem bestehende Probleme in der Funktionalität des Vorgängers Switch lösen.
Comparison Operator
Switch verwendet einen Typ konvertierenden Vergleichsoperator (==), was zu Problemen führen kann. Im Gegensatz dazu verwendet Match einen strikten Vergleichsoperator (===), unabhängig von strict_types.
Return Value
Switch Anweisungen erzeugen oft einen Wert, der später im Programmablauf benötigt wird. Hierbei kann es passieren, dass dieser Wert in der Switch Anweisung nicht gesetzt wird, was anschließend zu Problemen in dem PHP Skript führen kann. Zusätzlich ist durch die Syntax der Switch Anweisung die Lesbarkeit bei verschachtelten Switch Anweisungen nur schwer lesbar.
switch (1) {
case 0:
$y = 'Foo';
break;
case 1:
$y = 'Bar';
break;
case 2:
$y = 'Baz';
break;
}
echo $y;
//> Bar
Der neue Match Ausdruck beseitigt dieses Problem, indem für jeden Match Zweig der Rückgabewert direkt zugewiesen wird(=>), was intuitiver ist.
echo match (1) {
0 => 'Foo',
1 => 'Bar',
2 => 'Baz',
};
//> Bar
Fallthrough
Wenn ein Switch Statement nicht nach jedem Case einen Break aufweist, wird sie zum nächsten Case weiterlaufen, auch wenn der Code brechen sollte. Dies war vom Design her so ausgelegt, dass die Switch Funktionen mehrere Codeblöcke nacheinander ausführen können. Allerdings ist das bisher eine häufige Fehlerquelle gewesen.
Match hat einen impliziten Break nach jedem Zweig (=>) implementiert. Mehrere Bedingungen können nun durch Kommas zwischen den einzelnen Bedingungen ausgeführt werden:
match ($x) {
1, 2 => {
// Same for 1 and 2
},
3, 4 => {
if ($x === 3) {
// Only 3
}
// Same for 3 and 4
},
}
Throw expressions (rfc)
In PHP 8 ist die throw Anweisung zu einer Expression geworden. Das heißt, dass throw nun technisch gesehen einen Wert zurückgeben kann. Das ist in dem Sinne hilfreich, dass throw nun an viel mehr Stellen genutzt werden kann, wie z.B. die Arrow Functions oder Coalesce Operators.
Arrow Functions:
$callable = fn() => throw new Exception();
Coalesce Operators:
// $value is non-nullable.
$value = $nullableValue ?? throw new InvalidArgumentException();
// $value is truthy.
$value = $falsableValue ?: throw new InvalidArgumentException();
Ternary Operators:
// $value is only set if the array is not empty.
$value = !empty($array)
? reset($array)
: throw new InvalidArgumentException();
Static Return Type (rfc)
Wie dieses RFC besagt, ermöglicht Static Return Type die Rückgabe des speziellen Klassennamens „static“ von einer Methode: “The static special class name in PHP refers to the class a method was actually called on, even if the method is inherited. This is known as “late static binding” (LSB). This RFC proposes to make static also usable as a return type (next to the already usable self and parent types).”
Static kann in diesem Fall jedoch nicht als Teil eines Parameters verwendet werden. Die statische Rückgabe wird auf die Klasse verweisen, die aufgerufen wurde.
Union Types (rfc)
Union Types ermöglichen dir, den Typ des Wertes zu deklarieren, den du von einer Eingabe erwartest. In einigen Sprachen wird dies als Schema bezeichnet. Dies wird syntaktisch durch die Verwendung von |
(z.B. string|array|int
) definiert. Aber da hört die Magie noch nicht auf, denn du kannst außerdem definierte Klassen nutzen wie:
class MyClass {
}
function myFunction(string|array|int|MyClass){
}
Union Types werden bereits in PHP verwendet. Sie werden jedoch, wie unten gezeigt, mit der phpdoc Annotations Methode implementiert.
class Number {
/**
* @var int|float $number
*/
private $number;
/**
* @param int|float $number
*/
public function setNumber($number) {
$this->number = $number;
}
/**
* @return int|float
*/
public function getNumber() {
return $this->number;
}
}
Für etwas mehr Kontext über die Verwendung, sieh dir dieses Beispiel aus dem RFC an:
class Number {
private int|float $number;
public function setNumber(int|float $number): void {
$this->number = $number;
}
public function getNumber(): int|float {
return $this->number;
}
}
Dies alles läuft darauf hinaus, dass du mehrere Eingabetypen für dieselbe Funktion statt nur einen verwenden kannst, was einen höheren Grad an Wiederverwendbarkeit des Codes ermöglicht.
Mixed Types (rfc)
In neueren PHP Versionen war es möglich, den erwarteten Type von Input und Return Data zu deklarieren. PHP hat Types jedoch nicht immer unterstützt, und das ist ein Problem. In einigen Fällen wurde ein Type ausgelassen oder einfach vergessen. Mixed Types versucht nun, dieses Problem zu lösen.
Ein mixed
type wäre das Äquivalent zu array|bool|callable|int|float|null|object|resource|string
Hier ein Beispiel aus der RFC Doku, wie dies verwendet wird:
// Valid example
class A
{
public function foo(int $value) {}
}
class B extends A
{
// Parameter type was widened from int to mixed, this is allowed
public function foo(mixed $value) {}
}
Zusätzliche PHP 8 Features
Make Sorting Stable (rfc)
Stability wird zu allen Funktionen hinzugefügt, die unter Sort fallen (zum Beispiel.
sort, rsort, usort, asort, arsort, uasort, ksort, krsort, uksort, array_multisort).
Ich würde dir empfehlen, dies in der RFC Doku nachzulesen und mit deiner Anwendung zu vergleichen, da eine Änderung dieser Funktionalität von unstable zu stable Sorting deinen Code negativ beeinflussen könnte.
Constructor Property Promotion (rfc)
Dieses Feature soll dabei helfen, deinen Dev Workflow zu beschleunigen und Fehler zu reduzieren. Gegenwärtig erfordert die Definition eines Objektes von Werten eine Menge von Boilerplates, wie unten aus der RFC Dokumentation ersichtlich ist:
class Point {
public float $x;
public float $y;
public float $z;
public function __construct(
float $x = 0.0,
float $y = 0.0,
float $z = 0.0,
) {
$this->x = $x;
$this->y = $y;
$this->z = $z;
}
}
Bei dieser Methode müssen die Eigenschaften dreimal wiederholt werden. Die Verbesserung dazu ist die untenstehende Kurzformel:
class Point {
public function __construct(
public float $x = 0.0,
public float $y = 0.0,
public float $z = 0.0,
) {}
}
Nullsafe Operator (rfc)
Es gibt einen neuen Operator in diesem Block!
Anstelle des klassischen <code>!== null</code> haben wir nun das bekommen: <code>?-></code>. Es scheint zunächst merkwürdig, aber wenn man es unter dem Gesichtspunkt der Verkettung von „if-Statements“ betrachtet, dann wird die Anwendung ziemlich deutlich:
$country = null;
if ($session !== null) {
$user = $session->user;
if ($user !== null) {
$address = $user->getAddress();
if ($address !== null) {
$country = $address->country;
}
}
}
// do something with $country
$country = $session?->user?->getAddress()?->country;
// do something with $country
str_contains (rfc)
Diese ziemlich nette neue Funktion gibt einen booleschen Wert (true/false) zurück, wenn eine Zeichenkette in einer anderen Zeichenkette gefunden wird. Dazu werden zwei Argumente benötigt, die zu durchsuchende Zeichenkette und die Zeichenkette die gesucht werden soll.
str_contains('php8', '8'); // true
str_contains('php8', 'wordpress'); // false
Für noch mehr nützliche String Filter, solltest du dir folgende Neuerungen anschauen:
str_starts_with('haystack', 'hay'); // true
str_ends_with('haystack', 'stack'); // true
Diese beiden werden beide ein boolesches Ergebnis liefern und arbeiten auf die gleiche Weise wie str_contains()
.
Weak Maps (rfc)
Wenn du in PHP eine Variable auf den Wert eines Objekts setzt, wird normalerweise eine Referenz auf dieses Objekt erstellt, aber kein neues Objekt.
In diesem Fall kannst du also am Ende viele Referenzen auf ein Objekt haben, aber nur ein Objekt. Das Problem dabei ist: Wenn es an der Zeit ist, dieses Objekt zu löschen, zählt PHP die Anzahl der Referenzen, die dieses Objekt hat. Und wenn es mehr ist als das eine, wird PHP sich weigern, dieses Objekt zu löschen.
Weak Maps löst dieses Problem, indem es eine „schwache“ Referenz auf das entsprechende Objekt erstellt. Sobald das Objekt gelöscht ist, werden alle Variablen mit der Weak Maps Referenz auf dieses Objekt auf null gesetzt.
Non-capturing Catches (rfc)
Ein try-catch-Block ist schon ziemlich genial, wenn es um Error Reporting geht und nun gibt es einen noch schnelleren Weg dies zu implementieren. Und nein, das wird die Lesbarkeit nicht wirklich beeinträchtigen.
Der Weg der “alten Schule” bedeutete, dass du deine Catch Exception an eine Variable wie diese übergeben musstest:
function catchMeWhenIFall(){
try {
throw new Exception('NOPE - GRAVITY');
} catch (Exception $e) {
return $e->getMessage();
}
}
Aber jetzt brauchst du die Variable, die an deinen Catch Block übergeben werden soll, nicht mehr zu definieren.
try {
throw new Exception('FOO!');
catch (){
//Do some code here
}
}
Weiterer PHP 8 Lesestoff
Wenn du mehr über die Veröffentlichung von PHP 8 wissen oder die RFC Codebeispiele selbst durchsehen möchtest, dann wirf einfach einen Blick auf die offiziellen Release Meldung.
„*“ zeigt erforderliche Felder an
Bist du bereit für PHP 8?
Kein Entwickler ist Fan von Updates mit großen Veränderungen (wir erinnern uns an WordPress 5.0 und Gutenberg), wo die Gefahr besteht, dass dein Code bricht und stundenlange Arbeit oder ein kompletter Rebuild auf einen wartet. Wenn dein Code allerdings schon mit PHP 7.4. sauber funktioniert hat, solltest du mit PHP 8 eigentlich keine Probleme haben (mehr zum Thema PHP und WordPress im nächsten Kapitel).
Wenn du allerdings eine ältere PHP Version im Einsatz hast, solltest du die Liste von veralteten Funktionen vor dem Update überprüfen. In der PHP “Appendices” Dokumentation findest du eine vollständige Liste der bisherigen Features, Änderungen und Probleme beim Update von einer PHP Version zur nächsten.
WordPress auf PHP 8 updaten?
Dieses Zitat aus dem Yoast “WordPress and PHP 8 Compatibility Report” lässt bereits darauf schließen, dass du als WordPress User:in mit dem Update auf PHP 8 nicht leichtfertig umgehen solltest. Das Fazit des Reports verstärkt diese Annahme, denn Omar Reiss schreibt: “By just investigating a subset of breaking changes in PHP 8 we could already confirm this is likely to cause major breakage on sites with unclear origin of that breakage. Oftentimes the error will occur in one place, but is caused by a plugin or theme in a different place, making these issues hard to debug.“
Diese Kompatibilitätsprobleme waren auch der Grund, warum PHP 8 nicht sofort für unsere Kund:innen verfügbar war. Denn besonders nach Major Updates ist es immer sinnvoll, den Entwickler:innen von WordPress Plugins ausreichend Zeit für eventuelle Anpassungen zu geben und vorerst abzuwarten. Jetzt kannst du ganz einfach über das Raidboxes Dashboard deine Website auf PHP 8 oder PHP 8.1 updaten. Wie du eine neue PHP Version bei Raidboxes richtig testest, erklären wir in diesem Helpcenter Beitrag.
Unser Fazit zu PHP 8
PHP 8 ist ein großer Schritt nach vorn gegenüber seinen Vorgänger Versionen. Auch wenn du vielleicht nicht sofort eine dramatische Verbesserung der Leistung sehen wirst (je nachdem, wie du PHP 8 einsetzt), solltest du das Update in Betracht ziehen – zumindest nachdem du es getestet hast, es stabil läuft und bei deinem WordPress Hoster verfügbar ist. Die neue Version ist ein natürlicher Fortschritt, und indem du diese eher früher als später implementierst, schaffst du eine solide Grundlage für zukünftige Erweiterungen, Wachstum und künftige Performance Verbesserungen.
Weitere Fragen zu PHP 8?
Ich hoffe, ich konnte dir mit diesem Artikel die spannenden Neuerungen von PHP 8 näher bringen. Du hast noch weitere Fragen zu dem Thema? Nutze gerne die Kommentarfunktion. Du willst mehr Tipps zum Thema WordPress, Webdesign und mehr? Dann folge uns auf Twitter, Facebook oder über unseren Newsletter.
Ich kann mich nur bedanken. Hier kann man viele Tipps von Experten auf dieser Seite lesen. Man kann es ohne Probleme umsetzen. Da es verständlich lesbar ist.
Beste Grüße
Hallo Marten,
danke für den interessanten und informativen Artikel.
Gibt es hierzu schon Neuigkeiten bzw. neue Infos wie gut WordPress sich mit php 8.0 verträgt?
Viele Grüße Uli