Ein PHP-Namespace stellt Klassen, Funktionen und Konstanten unter ein Präfix, damit ihre Namen nicht mit denen anderer kollidieren. Du deklarierst ihn mit namespace App\Models; als erste Anweisung einer Datei, und andere Dateien sprechen die Klasse als \App\Models\User an oder importieren sie mit use App\Models\User; und schreiben nur User.
Im Namespace bedeutet User dasselbe wie App\Models\User. User::class liefert den vollen Namen als String, ohne etwas zu erzeugen, praktisch für Logging und für Autoloader.
Zwei Namespaces in einer Datei
Ein echtes Projekt legt einen Namespace pro Datei an. Für eine in sich geschlossene Demo darf eine Datei mehrere Namespaces enthalten, wenn jeder in geschweifte Klammern gesetzt ist. Code, der zu keinem Namespace gehört, kommt in namespace { }:
Zwei Klassen namens Order leben nebeneinander, weil sich ihre vollen Namen unterscheiden. Genau dieses Problem lösen Namespaces, sobald du Bibliotheken installierst: Dein Order, das Order einer Zahlungsbibliothek und das Order einer PDF-Bibliothek kollidieren nicht mehr.
Mit use importieren und mit as einen Alias vergeben
Überall \Shop\Order zu schreiben ist unübersichtlich. use am Anfang einer Datei (oder eines Namespace-Blocks) importiert einen Namen, sodass du die kurze Form verwenden kannst. Wenn zwei Importe auf denselben kurzen Namen enden würden, gibt as einem davon einen anderen Namen:
use erzeugt nur einen kurzen Namen für den Rest der Datei. Es lädt keine Datei und führt keinen Code aus und funktioniert gleich, ob die Klasse schon existiert oder nicht. Gruppierte Importe sind ebenfalls erlaubt: use Shop\{Order, Invoice};.
use function und use const
Funktionen und Konstanten in einem Namespace importierst du mit use function und use const:
Globale Klassen brauchen einen Backslash
In einem Namespace wird ein nicht qualifizierter Klassenname relativ zu diesem Namespace aufgelöst, also sucht new DateTime() in namespace App; nach App\DateTime. Bei Funktionen und Konstanten ist es anders: Existiert App\strlen nicht, fällt PHP auf das globale strlen zurück. Klassen fallen nie zurück.
catch (\Error $e) brauchte aus demselben Grund einen Backslash: Ohne ihn würde PHP nach App\Error suchen, den echten Fehler nie treffen, und das Skript würde mit einem nicht abgefangenen Error stoppen. Behebe es entweder mit einem führenden Backslash, wie oben, oder mit use DateTime; am Anfang der Datei. Dasselbe gilt für \Exception, \Throwable und jede andere eingebaute Klasse; siehe try catch zum Abfangen.
Autoloading und PSR-4
In einem Projekt lebt jede Klasse in ihrer eigenen Datei, und der Dateipfad folgt dem Namespace. PSR-4 ist die Konvention: Ein Namespace-Präfix wird einem Basisordner zugeordnet, und der Rest des Namens wird zum Pfad. Ein mit spl_autoload_register() registrierter Autoloader lädt dann eine Klassendatei, sobald die Klasse zum ersten Mal verwendet wird. Dieser Block schreibt zwei Klassendateien auf die Festplatte und lädt sie automatisch:
Jede Klassendatei wird einmal geladen, in dem Moment, in dem die Klasse zum ersten Mal gebraucht wird. In echten Projekten schreibst du diese Funktion nicht selbst: Composer erzeugt sie aus ein paar Zeilen in composer.json:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Nach composer dump-autoload lädt ein einziges require __DIR__ . '/vendor/autoload.php'; am Anfang deines Einstiegsskripts jede App\...-Klasse bei Bedarf.
Namespace-Regeln, die Fehler verursachen
namespacemuss die erste Anweisung der Datei sein. Nurdeclare(strict_types=1);und Kommentare dürfen davor stehen.use-Importe gelten pro Datei. Eine Klasse inindex.phpzu importieren, lässt den kurzen Namen nicht in einer eingebundenen Datei funktionieren; jede Datei braucht ihre eigenenuse-Zeilen.usegehört auf die oberste Ebene der Datei oder des Namespace-Blocks. In einem Klassenrumpf bedeutetuseetwas anderes: Es bindet einen Trait ein.- Strings werden nie aufgelöst:
$class = 'User'; new $class();sucht nach dem globalenUser. Speichere den vollen Namen, am besten mitUser::class.
Die letzte Regel verdient eine kurze Prüfung:
Häufig gestellte Fragen
Was ist ein Namespace in PHP?
Ein Präfix, das zusammengehörige Klassen, Interfaces, Funktionen und Konstanten gruppiert, wie ein Ordner für Namen. namespace App\Models; am Anfang einer Datei legt ihre Klasse User unter App\Models\User ab, sodass sie nicht mit dem User einer anderen Bibliothek kollidieren kann.
Was macht use in PHP?
use App\Models\User; am Anfang einer Datei erlaubt dir, in dieser Datei User statt des vollen Namens \App\Models\User zu schreiben. Es lädt und bindet nichts ein; die Klassendatei zu laden ist Aufgabe des Autoloaders. use ... as Alias; wählt einen anderen kurzen Namen.
Warum bekomme ich in einem Namespace Class not found?
In namespace App; wird ein bloßer Klassenname relativ zum Namespace aufgelöst, also sucht new DateTime() nach App\DateTime. Schreib new \DateTime() oder füge use DateTime; am Anfang hinzu. Funktionen und Konstanten fallen automatisch auf den globalen Namespace zurück, Klassen nicht.
Was bedeutet der Backslash vor einem Klassennamen in PHP?
Ein führender Backslash macht den Namen vollqualifiziert, ausgehend vom globalen Namespace: \Exception ist immer PHPs eingebaute Exception, egal in welchem Namespace der Code steht. Ohne ihn wird der Name relativ zum aktuellen Namespace und zu den use-Importen aufgelöst.
Wie hängen Namespaces mit Ordnern und PSR-4 zusammen?
PHP selbst verknüpft Namespaces nicht mit Ordnern. PSR-4 ist die Konvention, die das tut: Ein Präfix wie App\ wird einem Verzeichnis wie src/ zugeordnet, also liegt App\Models\User in src/Models/User.php. Der Autoloader von Composer folgt dem, und deshalb passen die beiden meist zusammen.