Typen können für Funktionsargumente, Rückgabewerte, seit PHP 7.4.0 für Klasseneigenschaften und seit PHP 8.3.0 für Klassenkonstanten deklariert werden. Dadurch wird sichergestellt, dass der Wert zum Zeitpunkt des Aufrufs vom angegebenen Typ ist und andernfalls ein TypeError geworfen.
Mit Ausnahme des Typs resource können alle von PHP unterstützten Typen in einer benutzerdefinierten Typdeklaration verwendet werden. Diese Seite enthält eine Changelog über die Verfügbarkeit der verschiedenen Typen und eine Dokumentation über ihre Verwendung in Typdeklarationen.
Hinweis:
Wenn eine Klasse eine Methode einer Schnittstelle implementiert oder eine Methode neu implementiert, die bereits von der Elternklasse definiert wurde, muss sie mit der obigen Definition kompatibel sein. Eine Methode ist kompatibel, wenn sie den Regeln der Kovarianz und Kontravarianz folgt.
Version | Beschreibung |
---|---|
8.3.0 | Unterstützung für die Typisierung von Klassen-, Interface-, Trait- und Enum-Konstanten wurde hinzugefügt. |
8.2.0 | Unterstützung für DNF-Typen wurde hinzugefügt. |
8.2.0 | Unterstützung für den literalen Typ true wurde hinzugefügt. |
8.2.0 | Die Typen null und false können nun eigenständig verwendet werden. |
8.1.0 | Unterstützung für Schnittmengentypen wurde hinzugefügt. |
8.1.0 | Die Rückgabe per Referenz aus einer void-Funktion ist nun veraltet. |
8.1.0 | Unterstützung für den Rückgabetyp never wurde hinzugefügt. |
8.0.0 | Unterstützung für mixed wurde hinzugefügt. |
8.0.0 | Unterstützung für den reinen Rückgabetyp static wurde hinzugefügt. |
8.0.0 | Unterstützung für Union-Typen wurde hinzugefügt. |
7.4.0 | Unterstützung für die Typisierung von Klasseneigenschaften wurde hinzugefügt. |
7.2.0 | Unterstützung für object wurde hinzugefügt. |
7.1.0 | Unterstützung für iterable wurde hinzugefügt. |
7.1.0 | Unterstützung für void wurde hinzugefügt. |
7.1.0 | Unterstützung für nullable Typen wurde hinzugefügt. |
Atomare Typen verhalten sich einfach, wobei es einige kleinere Einschränkungen gibt, auf die in diesem Abschnitt eingegangen wird.
Namens-Aliase für skalare Typen (bool, int,
float, string) werden nicht unterstützt.
Stattdessen werden sie wie die Namen von Klassen oder Schnittstellen
behandelt. Wird zum Beispiel boolean
als Typdeklaration
verwendet, muss der Wert ein instanceof
der Klasse oder Schnittstelle
boolean
sein, und nicht vom Typ bool:
<?php
function test(boolean $param) {}
test(true);
?>
Das oben gezeigte Beispiel erzeugt mit PHP 8 folgende Ausgabe:
Warning: "boolean" will be interpreted as a class name. Did you mean "bool"? Write "\boolean" to suppress this warning in /in/9YrUX on line 2 Fatal error: Uncaught TypeError: test(): Argument #1 ($param) must be of type boolean, bool given, called in - on line 3 and defined in -:2 Stack trace: #0 -(3): test(true) #1 {main} thrown in - on line 2
Hinweis:
Die Rückgabe per Referenz aus einer Funktion, die void zurückgibt, ist seit PHP 8.1.0 veraltet, da eine solche Funktion widersprüchlich ist. Vor PHP 8.1.0 gab sie bereits folgende
E_NOTICE
aus, wenn sie aufgerufen wurde: Only variable references should be returned by reference.<?php
function &test(): void {}
?>
Dieser Typ kann nicht als Typdeklaration für die Eigenschaft einer Klasse verwendet werden.
Hinweis: Es ist nicht möglich, eine Signatur für die Funktion anzugeben.
Wenn ein per Referenz übergebener Parameter eine Typdeklaration hat, wird der Typ der Variablen nur beim Eintritt in die Funktion, zu Beginn des Aufrufs, überprüft, nicht aber bei der Rückgabe der Funktion. Das bedeutet, dass eine Funktion den Typ einer Variablenreferenz ändern kann.
Beispiel #1 Typisierte Parameter, die per Referenz übergeben werden
<?php
function array_baz(array &$param)
{
$param = 1;
}
$var = [];
array_baz($var);
var_dump($var);
array_baz($var);
?>
Das oben gezeigte Beispiel erzeugt eine ähnliche Ausgabe wie:
int(1) Fatal error: Uncaught TypeError: array_baz(): Argument #1 ($param) must be of type array, int given, called in - on line 9 and defined in -:2 Stack trace: #0 -(9): array_baz(1) #1 {main} thrown in - on line 2
Bei der Deklaration von zusammengesetzten Typen gibt es mehrere Einschränkungen und um einfache Fehler zu vermeiden, wird bei der Kompilierung eine Redundanzprüfung durchgeführt.
Vor PHP 8.2.0, d. h. vor der Einführung von DNF-Typen, war es nicht möglich, Schnittmengentypen (Intersection-Typen) mit zusammengefassten Typen (Union-Typen) zu kombinieren.
Es ist nicht möglich, die beiden Singleton-Typen false und true in einem Union-Typ zu kombinieren; stattdessen kann bool verwendet werden.
Da false und null vor PHP 8.2.0 nicht als
eigenständige Typen verwendet werden konnten, war ein Union-Typ, der nur
aus diesen Typen bestand, nicht erlaubt. Hierbei handelt es sich um die
folgenden Typen: false, false|null
und
?false
.
Wenn ein einzelner Basistyp deklariert wird, kann dieser als nullable
gekennzeichnet werden, indem dem Typnamen ein Fragezeichen
(?
) vorangestellt wird. Somit bedeuten
?T
und T|null
dasselbe.
Hinweis: Diese Syntax wird seit PHP 7.1.0 unterstützt und geht der Unterstützung von allgemeinen Union-Typen voraus.
Hinweis:
Es ist auch möglich, nullable Parameter anzugeben, indem
null
zum Standardwert gemacht wird. Dies ist jedoch nicht empfehlenswert, denn wenn der Standardwert in einer Kindklasse geändert wird, wird eine Verletzung der Typkompatibilität ausgelöst, da der Typnull
zur Typdeklaration hinzugefügt werden muss.Beispiel #2 Die alte Methode, um Parameter nullable zu machen
<?php
class C {}
function f(C $c = null) {
var_dump($c);
}
f(new C);
f(null);
?>Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
object(C)#1 (0) { } NULL
Um einfache Fehler in Deklarationen von zusammengesetzten Typen abzufangen, führen redundante Typen, die ohne Laden einer Klasse erkannt werden können, zu einem Fehler beim Kompilieren. Dies schließt Folgendes ein:
int|string|INT
oder
Countable&Traversable&COUNTABLE
führen zu
einem Fehler.
Hinweis: Dies garantiert nicht, dass der Typ "minimal" ist, weil dies bedeuten würde, dass alle verwendeten Klassentypen geladen werden müssten.
Wenn zum Beispiel A
und B
Aliase von
Klassen sind, dann bleibt A|B
ein gültiger Union-Typ,
auch wenn er entweder auf A
oder B
reduziert werden könnte. Bei B extends A {}
ist
A|B
ebenfalls ein gültiger Union-Typ, auch wenn er auf
A
reduziert werden kann.
<?php
function foo(): int|INT {} // Unzulässig
function foo(): bool|false {} // Unzulässig
function foo(): int&Traversable {} // Unzulässig
function foo(): self&Traversable {} // Unzulässig
use A as B;
function foo(): A|B {} // Unzulässig ("use" ist Teil der Namensauflösung)
function foo(): A&B {} // Unzulässig ("use" ist Teil der Namensauflösung)
class_alias('X', 'Y');
function foo(): X|Y {} // Zulässig (Redundanz ist nur zur Laufzeit bekannt)
function foo(): X&Y {} // Zulässig (Redundanz ist nur zur Laufzeit bekannt)
?>
Beispiel #3 Grundlegendes Beispiel für die Deklaration eines Klassentyps
<?php
class C {}
class D extends C {}
// Das erweitert C nicht.
class E {}
function f(C $c) {
echo get_class($c)."\n";
}
f(new C);
f(new D);
f(new E);
?>
Das oben gezeigte Beispiel erzeugt mit PHP 8 folgende Ausgabe:
C D Fatal error: Uncaught TypeError: f(): Argument #1 ($c) must be of type C, E given, called in /in/gLonb on line 14 and defined in /in/gLonb:8 Stack trace: #0 -(14): f(Object(E)) #1 {main} thrown in - on line 8
Beispiel #4 Grundlegendes Beispiel für die Deklaration eines Schnittstellentyps
<?php
interface I { public function f(); }
class C implements I { public function f() {} }
// Das implementiert I nicht.
class E {}
function f(I $i) {
echo get_class($i)."\n";
}
f(new C);
f(new E);
?>
Das oben gezeigte Beispiel erzeugt mit PHP 8 folgende Ausgabe:
C Fatal error: Uncaught TypeError: f(): Argument #1 ($i) must be of type I, E given, called in - on line 13 and defined in -:8 Stack trace: #0 -(13): f(Object(E)) #1 {main} thrown in - on line 8
Beispiel #5 Grundlegendes Beispiel für die Deklaration eines Rückgabetyps
<?php
function sum($a, $b): float {
return $a + $b;
}
// Hier wird ein Gleitkommawert zurückgegeben.
var_dump(sum(1, 2));
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
float(3)
Beispiel #6 Zurückgeben eines Objekts
<?php
class C {}
function getC(): C {
return new C;
}
var_dump(getC());
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
object(C)#1 (0) { }
Beispiel #7 Deklaration eines nulllable Parameters
<?php
class C {}
function f(?C $c) {
var_dump($c);
}
f(new C);
f(null);
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
object(C)#1 (0) { } NULL
Beispiel #8 Deklaration eines nulllable Rückgabetyps
<?php
function get_item(): ?string {
if (isset($_GET['item'])) {
return $_GET['item'];
} else {
return null;
}
}
?>
Beispiel #9 Deklaration eines Klasseneigenschafts-Typs
<?php
class User {
public static string $foo = 'foo';
public int $id;
public string $username;
public function __construct(int $id, string $username) {
$this->id = $id;
$this->username = $username;
}
}
?>
Standardmäßig wandelt PHP Werte eines falschen Typs automatisch in den erwarteten Typ um, wenn dies möglich ist. Wenn an eine Funktion zum Beispiel ein Wert vom Typ int für einen Parameter übergeben wird, der einen Wert vom Typ string erwartet, dann erhält die Funktion eine Variable vom Typ string.
Der strikte Modus kann auf Dateibasis aktiviert werden. Im strikten Modus wird nur ein Wert akzeptiert, der genau der Typdeklaration entspricht, andernfalls wird ein TypeError geworfen. Die einzige Ausnahme von dieser Regel ist die Übergabe eines int-Wertes, wenn ein float-Wert erwartet wird.
Funktionsaufrufe innerhalb interner Funktionen sind von der
strict_types
-Deklaration nicht betroffen.
Um den strikten Modus zu aktivieren, wird die declare
-Anweisung zusammen
mit der strict_types
-Deklaration verwendet:
Hinweis:
Strikte Typisierung gilt für Funktionsaufrufe, die innerhalb einer Datei mit aktivierter strikter Typisierung gemacht werden, nicht für die Funktionen, die innerhalb dieser Datei deklariert sind. Wenn eine Funktion, die in einer Datei mit strikter Typisierung definiert ist, aus einer Datei aufgerufen wird, in der die strikte Typisierung nicht aktiviert ist, wird die Präferenz des Aufrufers (automatische Umwandlung des Typs, coercive typing) berücksichtigt und der Wert wird typkonvertiert.
Hinweis:
Die strikte Typisierung ist nur für skalare Typdeklarationen definiert.
Beispiel #10 Strikte Typisierung für die Werte von Argumenten
<?php
declare(strict_types=1);
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
?>
Das oben gezeigte Beispiel erzeugt mit PHP 8 folgende Ausgabe:
int(3) Fatal error: Uncaught TypeError: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 9 and defined in -:4 Stack trace: #0 -(9): sum(1.5, 2.5) #1 {main} thrown in - on line 4
Beispiel #11 Erzwungene Typisierung für die Werte von Argumenten
<?php
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
// Diese werden in Ganzzahlen umgewandelt: man beachte die folgende Ausgabe!
var_dump(sum(1.5, 2.5));
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
int(3) int(3)
Beispiel #12 Strikte Typisierung für Rückgabewerte
<?php
declare(strict_types=1);
function sum($a, $b): int {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1, 2.5));
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
int(3) Fatal error: Uncaught TypeError: sum(): Return value must be of type int, float returned in -:5 Stack trace: #0 -(9): sum(1, 2.5) #1 {main} thrown in - on line 5