Contact salesFree trial
Blog

PHP 8.0 Typ Verbesserungen

PHPMerkmaleLeistung
30 November 2020
Teilen Sie

PHP 8 bietet eine Vielzahl von Verbesserungen, neuen Funktionen und einen umfassenden Feinschliff, um die beliebteste serverseitige Sprache des Internets noch besser zu machen. Wir erklären Ihnen, was Sie über PHP 8 wissen müssen. Es ist eine aufregende neue Version, und wir werden nicht einmal alle Neuerungen behandeln! Es gibt einfach so viel zu tun.

Als Erstes werden wir uns mit den verschiedenen Verbesserungen am Typensystem befassen.

Vereinigungstypen

Die größte Änderung des Typsystems ist die Einführung von Vereinigungstypen. Vereinigungstypen sind ein virtueller Typ, der die "Vereinigung" (ein logisches "ODER") von zwei anderen Typen ist. Ein Beispiel:

<?php function mangleUsers(string|array $users): array { If (is_string($users)) { $users = [$users]; } // ... }

Wenn man früher den "one or many"-Parameterstil unterstützen wollte, konnte man den Parameter nicht eingeben. Jetzt kann man string|array angeben und entweder eine String- oder eine Array-Variable ist akzeptabel. Ganzzahlen, Objekte usw. werden weiterhin abgelehnt.

Union-Typen funktionieren bei Parametern, Rückgabetypen und Eigenschaftstypen, und sie unterstützen jeden Typ, den PHP unterstützt: Primitive, Objekte, benutzerdefinierte Klassen, usw. Sie können zwar dazu verwendet werden, um alle Arten von unschönen, inkonsistenten APIs zu erzeugen, aber das war schon vorher möglich. Zumindest können sie jetzt dokumentiert werden. Noch wichtiger ist, dass sich dadurch einige interessante Anwendungsfälle ergeben, die bisher im Typsystem selbst nicht dokumentiert werden konnten.

Zum Beispiel kann eine Funktion, die eine Zahl benötigt, aber sowohl mit Ints als auch mit Floats arbeiten kann, jetzt genau das sagen:

<?php function doMath(int|float): int|float { // ... }

Es ist auch möglich, explizit zu sagen, dass eine Funktion oder Methode Objekte unterschiedlichen Typs zurückgeben kann. Eine Funktion, die ein PSR-7-Anfrageobjektentgegennimmt und entweder eine neue Anfrage oder eine entsprechende Antwort zurückgibt, würde zum Beispiel so aussehen:

<?php function handleRequest(RequestInterface $req): RequestInterface|ResponseInterface { // ... }

Bei der Vererbung folgen Union-Typen denselben kovarianten/kontravarianten Regeln wie jeder andere Typ. Das heißt, die Methodenparameter einer Unterklasse dürfen eine breitere Typdefinition als die der übergeordneten Klasse annehmen (das Hinzufügen eines |Foo ist also OK, aber nicht das Entfernen), während ein Rückgabewert eine engere Typdefinition als die der übergeordneten Klasse angeben darf (das Entfernen von |Foo ist also OK, aber nicht das Hinzufügen).

Die Reflection-API wurde ebenfalls aktualisiert, um die Überprüfung von Union-Typen bei Funktionen und Eigenschaften zu unterstützen.

Weitere Einzelheiten sind im ursprünglichen RFC zu finden. Vielen Dank an Nikita Popov für diesen Beitrag.

Spezialisierte Unions

PHP verfügt bereits über eine Reihe von einmaligen Union-Typen, die in der Sprache definiert sind. iterable zum Beispiel ist effektiv ein Union-Typ für array|\Traversable. Nullable-Typen, wie z.B. Product, sind im Wesentlichen ein Union-Typ von null|Product.

Tatsächlich ist es jetzt möglich, null als Typ in einer Vereinigung anzugeben, aber nur in einer Vereinigung. So ist null|RequestInterface|ResponseInterface eine legale Typdefinition. Das Flag ? nullable ist jetzt eine Abkürzung für null|, wenn nur ein einziger anderer Wert zulässig ist.

Eine weitere Option, die nur für Union-Typen gilt, ist false. Dies dient hauptsächlich dazu, bestehende PHP-interne Funktionen zu unterstützen, die aufgrund von Fehleinschätzungen in den 1990er Jahren "einen Wert oder im Fehlerfall false" zurückgeben. Diese Funktionen können nun wie folgt geschrieben werden:

<?php function base64_decode(string $str, bool $strict = false): string|false {}

Diese Funktion dient nur zur Unterstützung von Legacy-Code, der seine API nicht ändern kann, um weniger schlecht zu sein. Bitte verwenden Sie sie nicht für neuen Code. Wie null kann auch false nicht als eigenständige Typdeklaration verwendet werden. Die Deklaration void kann auch nicht mit irgendetwas kombiniert werden, da sie buchstäblich "überhaupt nichts zurückgegeben wird, Punkt" bedeutet, so dass es wenig Sinn macht, sie mit anderen Typen zu kombinieren.

PHP 8 führt auch einen neuen eingebauten Union-Typ ein. Der neue gemischte Typ ist äquivalent zu array|bool|callable|int|float|null|object|resource|string. Das ist nicht ganz dasselbe wie das vollständige Weglassen des Typs. Das Weglassen des Typs könnte bedeuten, dass der Entwickler es einfach vergessen hat, oder dass das Typsystem nicht robust genug ist, um die möglichen zulässigen Werte zu beschreiben. Die Verwendung des gemischten Typs sagt der Engine und anderen Entwicklern explizit: "Ich akzeptiere hier alles, und ich meine es auch so." Es gibt nur noch extrem wenige Fälle, in denen es nicht möglich ist, einen Parameter, eine Rückgabe oder eine Eigenschaft in PHP 8 zu typisieren.

Vielen Dank an Máté Kocsis und Dan Ackroid für diesen RFC.

Die Stringable-Schnittstelle

PHP-Objekte können seit langem mit der magischen Methode __toString() in einen String umgewandelt werden. Allerdings akzeptiert der String-Typ-Hinweis im Strict-Modus keine String-castable-Objekte, was seit der Einführung skalarer Typen in PHP 7.0 weniger nützlich ist.

PHP 8 führt nun eine Stringable-Schnittstelle ein, die einem Objekt mit der magischen Methode __toString() entspricht. Und das auf eine clevere, rückwärtskompatible Weise.

Ab 8.0 kann eine Klasse eine Stringable-Schnittstelle implementieren, die eine Methode public function __toString(): string definiert. Wenn dies nicht der Fall ist, aber die Methode dennoch implementiert wird, fügt die Engine die Methode und den Rückgabetyp automatisch hinzu. Das bedeutet, dass jedes stringable Objekt jetzt typgeprüft werden kann, auch als Teil eines Union-Typs, wie zum Beispiel so:

<?php function show_message(string|Stringable $message): void { // ... }

Boom! __toString ist wieder nützlich.

Da die neue Schnittstelle technisch gesehen etwas strenger ist als die ursprüngliche __toString() -Methode (da sie eine String-Rückgabe erzwingt, anstatt sie einfach nur anzunehmen), hat das Symfony-Team ein Polyfill für sie in ihr symfony/polyfill-php80-Paket aufgenommen. Das erlaubt es Entwicklern, es jetzt zu benutzen, um sicherzustellen, dass ihre Typen korrekt sind und sofort für PHP 8 vorwärtskompatibel sind.

Wohlgemerkt, nur weil __toString() jetzt brauchbarer ist, heißt das nicht, dass man es übertreiben sollte. Die meisten Objekte sollten keine __toString() -Methode haben und stattdessen sinnvolle Methoden, die Strings zurückgeben. Wo __toString() nützlich ist, ist bei Wertobjekten, die nur eine einzige sinnvolle String-Darstellung haben, weil das Objekt im Grunde nur ein ausgefallener String ist. Ein gutes Beispiel ist ein IPv4Address-Objekt, bei dem es nur sinnvoll wäre, es in eine Zeichenkette vom Typ 1.2.3.4 zu verwandeln.

Vielen Dank an Nicolas Grekas für den Stringable RFC.

Kleinigkeiten

Schließlich gibt es noch zwei kleine Verbesserungen, die den täglichen Code erleichtern.

Erstens haben Objekte jetzt eine magische Konstante, die ihre Klasse spezifiziert, genau wie Klassennamen es tun. $object::class ist eine Zeichenkette, die den Klassennamen enthält, z. B. App\Form\FormDef. Es ist dasselbe wie get_class(), aber einfacher zu benutzen. Der Dank für diese Funktion geht wieder an Nikita Popov.

Und schließlich, ein persönlicher Favorit, können Methoden jetzt einen Rückgabetyp von static haben. Das ist vor allem für Schnittstellen mit verketteten Methoden nützlich. Das bedeutet, dass das Folgende nun möglich ist:

<?php Interface TaskBuilder { public function addStep(Step $s): static; } class ImportantTask implements TaskBuilder { public function addStep(Step $s): static { $this->steps[] = $s; return $this; } }

Und jetzt ist ImportantTask::addStep() so typisiert, dass sie eine Instanz von ImportantTask zurückgibt. Zuvor wurde bei einem Rückgabetyp von self nur angezeigt, dass ein TaskBuilder zurückgegeben wird.

Der Dank für diese Verbesserung geht wieder einmal an Nikita Popov. (Wir werden seinen Namen in dieser Serie noch oft sehen.)

Nützliche Links:

Ihr größtes Werk
steht vor der Tür

Kostenloser Test
Discord
© 2025 Platform.sh. All rights reserved.