PHP 8: eine neue Version der beliebten Programmiersprache für Internetanwendungen
PHP stellt eine der beliebtesten Programmiersprachen dar. Ihr wesentlicher Einsatzzweck besteht darin, dynamische Internetseiten zu gestalten. Laut einer Statistik von W³Techs verwenden im September 2020 78,9 Prozent aller serverseitig programmierten Websites PHP. Das stellt einen überragenden Marktanteil dar. Das zeigt, welche enorme Bedeutung PHP für das Internet hat.
Die technische Entwicklung des Internets in den letzten Jahren war beeindruckend. Insbesondere die Übertragungsgeschwindigkeiten haben enorm zugenommen. Hinzu kommen eine immer weitere Verbreitung und die immer häufigere Nutzung mobiler Endgeräte. Das führt dazu, dass auch die Programmiersprache PHP immer wieder an die aktuellen Entwicklungen angepasst werden muss. Die letzte Hauptversion – PHP 7 – erschien im Dezember 2015. Diese stellte eine wesentliche Weiterentwicklung zur vorherigen Version dar. Sie brachte beispielsweise eine Verbesserung der Ausführungsgeschwindigkeit um rund 30 Prozent mit sich. Nach dem ersten Erscheinen der Hauptversion kam es dann zu mehreren weiteren Überarbeitungen – bis hin zu PHP 7.4, das im November 2019 erschien.
Bereits seit einiger Zeit ist für Ende 2020 eine neue Hauptversion für PHP geplant. Mittlerweile ist das Datum für die Erscheinung festgelegt. PHP 8 soll am 26. November 2020 erscheinen. Eine Beta-Version ist bereits seit dem 8. August erhältlich. Diese wurde jedoch bereits mehrfach überarbeitet. Die aktuelle Beta-Version ist PHP 8.0.0 Beta 3 und erschien am 3. September 2020. Das gibt den PHP-Programmierern bereits die Möglichkeit, die neue Funktionen von PHP 8 auszuprobieren. Allerdings warnt das Entwickler-Team bislang ausdrücklich davor, diese Version für die Gestaltung von öffentlich zugänglichen Internetseiten zu verwenden, da sie noch zahlreiche Fehler enthalten kann. Sie dient daher lediglich zu Test-Zwecken.
Eine neue PHP-Version: Was bedeutet das?
Bevor wir auf die Details der Neuentwicklungen eingehen, ist es wichtig, sich zunächst damit auseinanderzusetzen, was es bedeutet, wenn eine neue PHP-Version erscheint. Dazu ist es notwendig, zunächst kurz auf die Funktionsweise von PHP-Anwendungen einzugehen. Wenn Sie ein Programm erstellen, enthält dieses verschiedene Funktionen, Variablen, Befehle und weitere Elemente. Um diese im Programm anzubringen, verwenden Sie Schriftzeichen und weitere Symbole. Hierbei handelt es sich jedoch um eine Text-Datei. Der Computer kann diese nicht direkt ausführen. Der Prozessor benötigt klare Anweisungen in Binärcode. Diese werden als Maschinensprache bezeichnet. Aus diesem Grund kommt ein sogenannter PHP-Interpreter zum Einsatz. Dieser übersetzt das Programm, das Sie geschrieben haben, in die Maschinensprache. Erst so wird die Ausführung möglich.
Wenn nun eine neue PHP-Version erscheint, bedeutet dies, dass der PHP-Interpreter überarbeitet wurde. Daher steht eine neue Version dieser Software zur Verfügung. Das hat Auswirkungen auf zwei Ebenen. Zum einen werden hierbei die internen Prozesse des Interpreters überarbeitet. Es ist möglich, den Ablauf des Übersetzungsprozesses so zu optimieren, dass dieser weniger Ressourcen benötigt und schneller abläuft. Das führt zu einer besseren Performance der PHP-Programme.
Die zweite Ebene ist die Erstellung des Programmcodes. Der PHP-Interpreter akzeptiert verschiedene Befehle und macht genaue Anforderungen an die Struktur und an die Syntax der Programme. Auf diese Weise gibt er die Regeln der Programmiersprache vor. Nur wenn Ihr Code diese Regeln beachtet und wenn er die vom PHP-Interpreter unterstützten Befehle verwendet, ist eine Ausführung möglich. Bei der Entwicklung einer neuen PHP-Version werden auch die Anforderungen überarbeitet, die der Interpreter an den Code stellt. Meistens bringen neue Versionen einige neue Befehle mit sich, die die Möglichkeiten für die Programmgestaltung erweitern. Oftmals werden auch einige ältere Befehle beseitigt, die in der Vergangenheit Probleme mit sich brachten oder die nicht mehr den aktuellen Anforderungen entsprechen. Allerdings handelt es sich hierbei in der Regel nur um punktuelle Änderungen. Der überwiegende Teil der Befehle und Syntaxregeln bleibt dabei erhalten.
Major Release: Abwärtskompatibilität ist nicht gegeben
Bei PHP 8 handelt es sich um ein sogenanntes Major Release. Das bedeutet, dass hierbei recht umfangreiche Änderungen umgesetzt wurden. Dabei ist es insbesondere wichtig zu beachten, dass hierbei keine Abwärtskompatibilität gegeben ist. Das bedeutet, dass Sie ein Programm, das für eine frühere Version von PHP entwickelt wurde, eventuell nicht mit einem PHP8-Interpreter ausführen können.
Allerdings sind die Änderungen hierbei wie gesagt punktuell. Das bedeutet, dass davon nur wenige Befehle betroffen sind. Nur bei Programmen, die genau diese Kommandos verwenden, kommt es bei der Umstellung zu Problemen. Insbesondere bei einfachen Programmen, die nur aus den grundlegenden Befehlen bestehen, sollte die Ausführung auch weiterhin möglich sein.
Insbesondere bei professionellen Anwendungen ist es dennoch sehr wichtig, diesen Punkt genau abzuklären, bevor Sie auf die neue PHP-Version umsteigen. Wenn Sie für Ihre Internetseite ein älteres Programm verwenden, das für eine der bisherigen Versionen entwickelt wurde, ist es empfehlenswert, auch weiterhin die ältere Ausführung des Interpreters zu verwenden. Erst nach einer ausführlichen Prüfung des Programms sollte der Umstieg erfolgen.
Mehr Effizienz durch JIT-Compiler
Bei PHP 8 kam es zu einer erheblichen Überarbeitung der internen Strukturen. Dafür ist in erster Linie die Einführung des Just-In-Time-Compilers (JIT-Compiler) verantwortlich. Dieser verändert den Ablauf des Übersetzungsprozesses deutlich. Die folgenden Absätze stellen dessen Funktionsweise stark vereinfacht dar.
Um ein Programm auszuführen, ist es wie bereits beschrieben notwendig, den Quellcode in die Maschinensprache zu übersetzen. Dabei handelt es sich um einen Prozess, der recht viele Ressourcen des Systems – also in erster Linie Prozessorleistung und Arbeitsspeicher – in Anspruch nimmt. Daher kann diese Aufgabe einige Zeit in Anspruch nehmen.
Um die Ausführung des Programms zu ermöglichen, bestehen zwei verschiedene Möglichkeiten. Eine besteht darin, es zu kompilieren. Das bedeutet, dass der Übersetzungsprozess ein einziges Mal ausgeführt wird. Der Compiler erstellt dabei ein ausführbares Programm in Maschinensprache und speichert dieses ab. Daher steht es fortan direkt in seiner übersetzten Form zur Verfügung. Daher ist für alle weiteren Ausführungen kein Übersetzungsprozess mehr notwendig. Das spart Ressourcen und führt daher zu einer schnellen Ausführung. Diese Form der Übersetzung kommt beispielsweise bei den Programmiersprachen C und C++ zum Einsatz. Daher sind diese sehr effizient.
Andere Programmiersprachen werden hingegen interpretiert. Das bedeutet, dass der Übersetzungsprozess hierbei jedes Mal aufs Neue ausgeführt wird. Auch diese Vorgehensweise bringt einige Vorteile mit sich. Beispielsweise führt sie zu einer hohen Plattformunabhängigkeit. Das bedeutet, dass Sie das Programm problemlos auf andere Betriebssysteme übertragen können. Voraussetzung ist lediglich, dass dort ein entsprechender Interpreter installiert ist. Allerdings leidet darunter die Effizienz. Insbesondere bei umfangreichen Programmen kann es daher zu einiger Wartezeit kommen. Bei PHP handelt es sich um eine interpretierte Programmiersprache. Weitere wichtige Beispiele hierfür sind Python und JavaScript.
PHP 8 verwendet nun einen JIT-Compiler. Das führt dazu, dass die Grenzen zwischen interpretierter und kompilierter Programmiersprache verschwimmen. Bei der Ausführung eines Programms treten in der Regel einige Abschnitte auf, die sehr häufig wiederholt werden. Diese jedes Mal erneut zu übersetzen, würde einen erheblichen Aufwand mit sich bringen. Der JIT-Compiler überwacht nun jedoch die Ausführung des Programms und erkennt die Bereiche, die sich häufig wiederholen. Diese kompiliert er und speichert sie intern in Maschinensprache ab. Dies erfolgt Just in Time – also während der Ausführung. Die kompilierten Bereiche stehen daher bei der weiteren Ausführung des Programms bereits zur Verfügung. Daher ist es nicht notwendig, sie erneut zu übersetzen. Der Interpreter kann direkt auf diese Bestandteile zugreifen. Das verbessert die Performance bei der Ausführung deutlich.
Die Auswirkungen auf die Praxis
Nun stellt sich noch die Frage, wie sich die Einführung des JIT-Compilers in der Praxis auswirkt. Erste Tests haben ergeben, dass einzelne Programme auf diese Weise deutlich schneller ablaufen. Das könnte auch einen erheblichen Einfluss auf die Programmgestaltung haben. Bei Anwendungen, bei denen eine hohe Effizienz erforderlich ist, ist es bisher üblich, einige Bestandteile des Programms in einer kompilierten Sprache zu verfassen – beispielsweise in C. Das PHP-Programm ruft diese C-Programme im Rahmen der Webanwendung dann auf. Das kann die Performance zwar deutlich erhöhen. Allerdings erschwert die Verwendung von zwei unterschiedlichen Sprachen die Programmgestaltung deutlich. Durch die bessere Performance von PHP 8 scheint es möglich, dass Sie darauf fortan selbst bei rechenintensiven Programmen, bei denen eine gute Performance wichtig ist, verzichten können. Das bedeutet, dass es nun möglich sein wird, auch diese Programme vollständig in PHP zu verfassen.
Allerdings haben die ersten Tests auch ergeben, dass diese Verbesserung bei Real-Life-Anwendungen wie etwa WordPress und anderen Content-Management-Systemen nur sehr geringe Auswirkungen hat. Mögliche Gründe hierfür bestehen darin, dass hierbei noch viele weitere Elemente die Performance beeinträchtigen – wie etwa die Interaktion mit den Datenbanken oder HTTP-Anfragen. Dennoch wollen die Entwickler die Leistung von PHP in diesem Bereich genau im Auge behalten und an einer weiteren Optimierung arbeiten.
Zahlreiche neue Möglichkeiten für die Programmgestaltung in PHP 8
Neben der Überarbeitung der internen Strukturen bei der Ausführung kam es bei PHP 8 auch zu einigen Neuerungen, die Einfluss auf die Programmgestaltung haben. Die aktuelle Version unterstützt zahlreiche neue Befehle und hält einige Neuerungen bezüglich der Syntax bereit. Diese bieten viele neue Möglichkeiten bei der Gestaltung eines PHP-Programms und machen diese Aufgabe in einigen Bereichen deutlich einfache rund effizienter.
Die Zahl der neuen Möglichkeiten ist sehr umfassend. Daher ist es an dieser Stelle nicht möglich, diese alle detailliert zu beschreiben. Stattdessen erhalten Sie in den folgenden Abschnitten einen Überblick über einige wichtige Neuerungen, die aller Voraussicht nach einen recht großen Einfluss auf die Programmgestaltung haben und daher häufig zum Einsatz kommen werden.
Präzise Vorgaben für die Übergabewerte durch Named Arguments
Eine wichtiger Neuerung, durch die sich PHP 8 auszeichnet, besteht in der Unterstützung von Named Arguments – manchmal auch als Named Parameters bezeichnet. Diese neue Eigenschaft gestaltet den Aufruf von Funktionen oder Methoden in vielen Fällen etwas einfacher und flexibler.
Um die Funktionsweise von Named Arguments zu verstehen, erstellen wir eine kleine Funktion, die drei Werte als Übergabewert erhält. Sie multipliziert diese Eingaben mit verschiedenen Werten, addiert diese daraufhin und gibt das Ergebnis zurück:
function addieren ($wert1, $wert2, $wert3){ return $wert1 + 2$wert2 + 3$wert3; }
Bislang war es in PHP notwendig, beim Aufruf der Funktion genau die vorgegebene Reihenfolge zu beachten. Der erste Wert, der hier genannt wird, wird automatisch der ersten Variable zugewiesen. Die zweite Variable erhält den zweiten übergebenen Wert und so weiter. Named Arguments machen es nun jedoch möglich, beim Aufruf der Funktion den entsprechenden Namen der Variable anzugeben. Auf diese Weise lässt sich die Reihenfolge beliebig verändern:
$ergebnis = addieren (wert2: 5, wert3: 7, wert1: 2);
In diesem Beispiel bieten die benannten Übergabewerte zwar eine etwas höhere Flexibilität, doch ist der Nutzen hierbei recht gering. Von größerer Bedeutung wird diese Möglichkeit, wenn wir sogenannte Standardwerte verwenden. Dabei geben wir der Variable einen Wert, den sie einnehmen soll, falls kein Übergabewert angegeben ist. Beispielsweise könnten wir für alle drei Variablen den Wert 0 vorgeben:
function addieren ($wert1 = 0, $wert2 = 0, $wert3 = 0){ return $wert1 + 2$wert2 + 3$wert3; }
Nun wäre es beispielsweise möglich, die Funktion addieren() mit nur einem Parameter aufzurufen:
$ergebnis = addieren(2);
In diesem Fall wird wieder die Reihenfolge berücksichtigt. Das bedeutet, dass der vorgegebene Wert der ersten Variable zugewiesen wird. Da für die übrigen beiden Variablen keine Angaben gemacht wurden, erhalten diese den Standardwert, also 0. Nun kann es jedoch auch vorkommen, dass wir nur für die zweite oder für die dritte Variable einen Wert vorgeben möchten, nicht jedoch für die erste. Das ist bisher mit PHP nicht möglich. Das bedeutet, dass wir in diesem Fall den Standardwert der ersten Variable nicht nutzen können. Mit Named Arguments wird dies nun möglich. Wenn Sie beispielsweise nur der dritten Variable einen Wert zuweisen möchten, den ersten beiden hingegen nicht, können Sie die Funktion auf folgende Weise aufrufen:
$ergebnis = addieren (wert3: 7);
Mehr Speichereffizienz durch Weak Maps
PHP ist mit einem sogenannten Garbage Collector ausgestattet. Dieser löscht Elemente, die im Programm nicht mehr benötigt werden. Auf diese Weise wird der entsprechende Speicherplatz wieder freigegeben. Dieser Vorgang läuft vollkommen automatisch ab. Bei der Programmgestaltung ist es daher nicht notwendig, dass Sie sich selbst darum kümmern, nicht mehr benötigte Elemente zu löschen.
Um keine Elemente zu löschen, die Sie im weiteren Programmverlauf noch benötigen, wird der Garbage Collector nur dann aktiv, wenn keine Referenz mehr auf die entsprechenden Werte verweist. In den meisten Fällen funktioniert der Garbage Collector ausgezeichnet und sorgt für eine effiziente Nutzung des Speichers. Probleme treten jedoch dann auf, wenn das Programm ein Cache implementiert. Das ist beispielsweise bei ORM-Anwendungen sinnvoll, um die Performance zu verbessern. Das Problem beim Einsatz des Garbage Collectors besteht darin, dass dieser die Objekte nur dann löscht, wenn überhaupt keine Referenz mehr auf sie verweist. Solange noch eine Referenz aus dem Cache besteht, wird der entsprechende Speicherplatz nicht freigegeben – selbst wenn die Werte im eigentlichen Programm nicht mehr benötigt werden. Das kann die Effizienz des Programms stark reduzieren – insbesondere vor dem Hintergrund, dass hierbei oftmals große Mengen an Werten gespeichert werden. Wenn Sie hingegen eine WeakMap verwenden, hat das zur Folge, dass eine Löschung durch den Garbage Collector auch in diesem Fall möglich ist.
Verbesserungen bei der Implementierung der Vererbung
Die objektorientierte Programmierung ermöglicht es, hierarchische Strukturen zu erstellen. Ein untergeordnetes Element sollte dabei stets die gleichen Strukturen beachten wie das übergeordnete Element. Bei der Implementierung von Interfaces wird diese Vorgabe auch bisher schon konsequent umgesetzt. Dabei können Sie beispielsweise einen Methodennamen und die Rückgabe- und Übergabewerte mit ihren jeweiligen Datentypen festlegen. Wenn eine Klasse ein Interface implementiert, muss sie diese Vorgaben berücksichtigen. Tut sie dies nicht, kommt es zu einem Fehler.
Um dies zu demonstrieren, erstellen wir ein Interface:
interface meinInterface { public function meineMethode(int $a); }
Dieses Interface gibt vor, dass in jeder Klasse, die daraus abgeleitet wird, eine Methode mit der Bezeichnung meineMethode() enthalten sein muss, die eine ganze Zahl als Übergabewert erhält. Wenn wir nun das Interface in einer Klasse implementieren und einen anderen Datentyp für die Methode vorgeben, kommt es zu einem Fehler:
class meineKlasse implements meinInterface{ public function meineMethode(array $a) {} }
Wenn wir allerdings eine Klasse von einer anderen Klasse ableiten, ist die Kontrolle der Strukturen bislang nicht verbindlich. Wenn Sie in der abgeleiteten Klasse eine Methode überschreiben, können Sie hierfür auch einen anderen Datentyp als in der Eltern-Klasse vorgeben:
class meineKlasse{ public function meineMethode(int $a) {} } class meineAbgeleiteteKlasse extends meineKlasse{ public function meineMethode(array $a) {} }
Bei diesem Code kommt es bisher nur zu einer Warnmeldung. Das bedeutet, dass sich das Programm trotzdem ausführen lässt. Dem Prinzip der Vererbung folgend, sollten die Vorgaben der Eltern-Klasse jedoch auch für die abgeleitete Klasse verbindlich gelten. PHP 8 korrigiert dieses Verhalten und führt dazu, dass in diesem Fall fortan eine Fehlermeldung erscheint und dass sich das Programm nicht ausführen lässt.
Flexibilität bei der Vorgabe von Datentypen: Union Types verwenden
PHP zeichnet sich durch eine dynamische Typisierung aus. Das bedeutet, dass es beim Erstellen von Variablen nicht notwendig ist, einen Datentyp vorzugeben. Der Interpreter erkennt automatisch den verwendeten Typ und richtet die Variable entsprechend ein. Auch beim Erstellen von Funktionen oder Methoden ist es nicht notwendig, den Datentyp anzugeben.
Obwohl es nicht erforderlich ist, den Datentyp vorzugeben, ist dies dennoch möglich. Das kann in einigen Fällen Vorteile bieten. Beispielsweise können Sie auf diese Weise verhindern, dass die Funktion mit einem unpassenden Datentyp aufgerufen wird. Dadurch kommt es bei unpassenden Werten zu einer Fehlermeldung. So vermeiden Sie, dass das Programm mit unsinnigen Werten weiter ausgeführt wird. Ein Beispiel hierfür kann eine Funktion sein, die eine Zahl erhält, diese um 2 erhöht und diesen Wert dann zurückgibt:
function erhoehen ($wert){ return $wert + 2; }
Wenn Sie diese Funktion nun beispielsweise mit einer Zeichenkette aufrufen, erhalten Sie zwar eine Warnmeldung. Es kommt aber nicht zu einem Fehler. Die Zeichenkette wird bei der Addition als 0 gewertet. Daher erhalten Sie insgesamt den Wert 2 zurück. Da das Programm dabei nicht abgebrochen wird, können Sie diesen Wert für weitere Berechnungen verwenden – obwohl dieser nicht auf die korrekte Weise zustande gekommen ist. Um zu vermeiden, dass sich der Fehler durch das gesamte Programm zieht, ist es besser, hierbei einen Fehler zu erzeugen, der zu einem Abbruch führt.
Zu diesem Zweck können Sie auch bei den bisherigen PHP-Versionen einen Datentyp vorgeben:
function erhoehen (int $wert){ return $wert + 2; }
Das führt dazu, dass Sie diese Funktion jetzt nur noch mit einem int-Wert aufrufen können – also mit einer ganzen Zahl. Halten Sie sich nicht daran, kommt es zu einem Fehler. Häufig tritt jedoch das Problem auf, dass eine Funktion nicht nur für einen Datentyp geeignet ist, sondern für mehrere. Dennoch gibt es andere Datentypen, bei denen die Ausführung nicht möglich sein soll. Auch hierfür können wir wieder das obige Beispiel heranziehen. Hierbei soll ein Abbruch erfolgen, wenn Sie eine Zeichenkette übergeben. Die Funktion soll jedoch sowohl bei ganzen Zahlen als auch bei Fließkommazahlen das richtige Ergebnis berechnen. Das ist bislang nicht möglich. Mit den Union Types, die PHP 8 einführt, können Sie jedoch mehrere Datentypen angeben:
function erhoehen (int|float $wert){ return $wert + 2; }
Einfacherer Umgang mit Werten für Zeit- und Datumsangaben
PHP unterstützt verschiedene Formen, um Zeit- und Datumsangaben zu verwenden. Häufig kommen beispielsweise die Typen DateTime und DateTimeImmutable zum Einsatz. Beide ermögliche es, eine genaue Datumsangabe mit einer Uhrzeit aufzunehmen. Der Unterschied besteht darin, dass sich die Werte beim ersten genannten Datentyp verändern lassen, beim zweiten hingegen nicht.
Oftmals ist es jedoch erwünscht, eine Angabe aus einem dieser beiden Typen in einen anderen Typ zu konvertieren. Dies war bislang nicht möglich. PHP 8 führt jedoch die beiden neuen Funktionen DateTime::createFromInterface() und DatetimeImmutable::createFromInterface() ein, die diese Umwandlung erlauben.
Fazit: PHP 8 bietet zahlreiche neue Möglichkeiten
Dieser Artikel hat gezeigt, dass PHP 8 viele wichtige Neuerungen mit sich bringt. Von besonderer Bedeutung ist hierbei der JIT-Compiler, der die Performance bei der Ausführung deutlich erhöhen kann. Das kann auch erhebliche Auswirkungen auf die Programmgestaltung haben. Bislang rufen zahlreiche PHP-Programme einzelne Bereiche auf, die in einer anderen Programmiersprache erstellt wurden, um ihre Performance zu erhöhen. Durch die Verwendung des JIT-Compilers wird dies nun jedoch immer seltener notwendig sein. So ist es möglich, den kompletten Code in PHP zu erstellen und dabei dennoch eine effiziente Ausführung zu erzielen.
Hinzu kommen zahlreiche neue Befehle. Die Grundlagen der Programmiersprache bleiben damit zwar die gleichen. Allerdings können Union Types, Weak Maps oder Named Arguments die Codeerstellung erleichtern oder zu einer effizienteren Ausführung des Programms führen.
Wenn Sie PHP 8 nutzen möchten, müssen Sie jedoch darauf achten, dass die neue Version nicht abwärtskompatibel ist. Sie können daher nicht einfach ein PHP7-Programm mit einem PHP8-Interpreter ausführen, um von der höheren Effizienz zu profitieren. Dabei könnte es zu Fehlern kommen. Daher ist es bei allen bisherigen Programmen wichtig, genau zu überprüfen, ob diese auch dem PHP8-Standard entsprechen und gegebenenfalls Anpassungen vorzunehmen.