Einleitung: Was sind Generics und warum sind sie in PHP wichtig
Die moderne Entwicklung mit PHP erfordert zunehmend strenge Typisierung und wiederverwendbaren Code. Eines der wichtigsten Werkzeuge, um diese Ziele zu erreichen, sind Generics (Verallgemeinerungen oder Generika). In PHP wurde die Unterstützung für Generics offiziell ab Version PHP 8.0 hinzugefügt, obwohl es zuvor verschiedene Hilfsprogramme und Annotationen gab (z. B. über PHPDoc).
In diesem Artikel werden wir untersuchen, warum Generics in PHP nötig sind, wie sie in der Praxis funktionieren, und konkrete Codebeispiele liefern, die Ihnen helfen, sichereren, lesbareren und skalierbareren Code zu schreiben.
Warum sind Generics in PHP nötig?
Das Hauptziel von Generics ist es, Typsicherheit zur Laufzeit zu gewährleisten, ohne die Flexibilität von verallgemeinertem Code zu verlieren. Stellen Sie sich vor, Sie schreiben eine Funktion für die Arbeit mit einer Sammlung von Elementen. Ohne Generics verwenden Sie entweder gemischte Typen (mixed) oder schreiben separate Funktionen für jeden Datentyp. Beide Ansätze führen zu Fehlern und Code-Duplizierung.
Hier sind die wichtigsten Vorteile der Verwendung von Generics:
- Typsicherheit – Typfehler werden bereits zur Kompilierzeit erkannt, nicht erst zur Laufzeit.
- Wiederverwendbarkeit von Code – Eine Funktion oder Klasse arbeitet mit beliebigen Datentypen.
- Lesbarkeit – Der Code wird selbstdokumentierend: Man sieht sofort, welche Typen akzeptiert und zurückgegeben werden.
- Integration mit IDEs – Moderne Editoren (PhpStorm, VS Code) verstehen Code mit Generics besser und bieten Autovervollständigung und Hinweise an.
Wie funktionieren Generics in PHP: Syntax und grundlegende Konstrukte
In PHP werden Generics durch Typvorlagen implementiert, die in spitzen Klammern <T> angegeben werden. Der Buchstabe T ist ein Platzhalter für den Typ, der beim Aufruf der Funktion oder beim Erstellen eines Objekts eingesetzt wird. Sie können beliebige Namen verwenden: T, K, V oder aussagekräftige Bezeichnungen.
1. Verallgemeinerte Funktionen
Betrachten wir ein einfaches Beispiel – eine Funktion, die das erste Element eines Arrays zurückgibt:
<?php
function firstElement(array $items): mixed { return $items[0] ?? null;}
// Verwendung$numbers = [1, 2, 3];$first = firstElement($numbers); // Typ mixed, IDE weiß nicht, dass es int istMit Generics können wir angeben, dass die Funktion mit einem Array von Elementen beliebigen Typs arbeitet, aber genau den Typ zurückgibt, der übergeben wurde:
<?php
/** * @template T * @param array<T> $items * @return T|null */function firstElement(array $items): mixed { return $items[0] ?? null;}
// Jetzt versteht die IDE, dass $first — int|null ist$first = firstElement([1, 2, 3]);Beachten Sie: In PHP 8.0+ werden Generics über PHPDoc-Annotationen unterstützt. Eine native Unterstützung (ohne Kommentare) gibt es derzeit noch nicht, aber dies ist der De-facto-Standard für moderne Projekte.
2. Verallgemeinerte Klassen
Das häufigste Anwendungsszenario für Generics sind Sammlungsklassen. Erstellen wir eine einfache Klasse Collection, die Elemente beliebigen Typs speichern kann:
<?php
/** * @template T */class Collection { /** @var array<T> */ private array $items = [];
/** * @param T $item * @return void */ public function add(mixed $item): void { $this->items[] = $item; }
/** * @return T|null */ public function get(int $index): mixed { return $this->items[$index] ?? null; }
/** * @return array<T> */ public function all(): array { return $this->items; }}
// Verwendung$intCollection = new Collection<int>();$intCollection->add(10);$intCollection->add(