FAQ: Dinge, die Sie über Namespaces wissen sollten
(PHP 5 >= 5.3.0, PHP 7, PHP 8)
Diese häufig gestellten Fragen (FAQ) wurden in zwei Abschnitte aufgeteilt:
allgemeine Fragen und einige Implementierungsdetails, deren
vollständiges Verständnis hilfreich sein kann.
Zuerst die allgemeinen Fragen.
-
Wenn ich keine Namespaces
verwende, sollte mich das alles hier überhaupt interessieren?
-
Wie verwende ich interne
oder globale Klassen in einem Namespace?
-
Wie verwende ich Klassen,
Funktionen oder Konstanten mit Namespaces in ihrem eigenen Namespace?
-
Wie wird ein Name wie
\mein\name
oder
\name
aufgelöst?
-
Wie wird ein Name
wie
mein\name
aufgelöst?
-
Wie wird ein
unqualifizierter Name wie
name
aufgelöst?
-
Wie wird ein
unqualifizierter Funktions- oder Konstantenname wie
name
aufgelöst?
Es gibt einige Implementierungsdetails von Namespaces, deren
Verständnis hilfreich ist.
-
Importierte Namen
dürfen keine Konflikte mit Klassennamen in der gleichen Datei erzeugen.
-
Verschachtelte
Namespaces sind nicht erlaubt.
-
Dynamische Namespacenamen
sollten den Backslash escapen.
-
Zugriff auf
undefinierte Konstanten mit Backslashes beendet das Skript mit
einem fatal error.
-
Die speziellen Konstanten
null
, true
und false
können nicht überschrieben werden.
Wenn ich keine Namespaces verwende, sollte mich das alles
hier überhaupt interessieren?
Nein. Namespaces haben keinerlei Einfluss auf bereits bestehenden Code
oder irgendwelchen Code der noch geschrieben wird, der keine Namespaces
verwendet. Sie können folgenden Code schreiben, wenn Sie dies wünschen:
Beispiel #1 Zugriff auf globale Klassen außerhalb eines Namespace
<?php
$a = new \stdClass;
?>
Dies ist äquivalent zu:
Beispiel #2 Zugriff auf globale Klassen außerhalb eines Namespace
<?php
$a = new stdClass;
?>
Wie verwende ich interne oder globale Klassen in einem Namespace?
Beispiel #3 Zugriff auf interne Klassen in Namespaces
<?php
namespace foo;
$a = new \stdClass;
function test(\ArrayObject $parameter_type_example = null) {}
$a = \DirectoryIterator::CURRENT_AS_FILEINFO;
// erben von einer internen oder globalen Klasse
class MyException extends \Exception {}
?>
Wie verwende ich Klassen, Funktionen oder Konstanten mit Namespaces
in ihrem eigenen Namespace?
Beispiel #4 Zugriff auf interne Klassen, Funktionen oder Konstanten in Namespaces
<?php
namespace foo;
class MyClass {}
// verwendet eine Klasse des aktuellen Namensraumes als Parametertyp
function test(MyClass $parameter_type_example = null) {}
// eine andere Möglichkeit, eine Klasse des aktuellen Namensraums
// als Parametertyp zu verwenden
function test(\foo\MyClass $parameter_type_example = null) {}
// ableiten von einer Klasse aus dem aktuellen Namespace
class Extended extends MyClass {}
// Zugriff auf eine globale Funktion
$a = \globalfunc();
// Zugriff auf eine globale Konstante
$b = \INI_ALL;
?>
Wie wird ein Name wie \mein\name
oder
\name
aufgelöst?
Namen, die mit einem \
beginnen, werden immer
zu exakt dem aufgelöst wie sie aussehen. \mein\name
ist also tatsächlich \mein\name
und
\Exception
ist Exception
.
Beispiel #5 Vollständig qualifizierte Namen
<?php
namespace foo;
$a = new \my\name(); // erzeugt ein Objekt der Klasse "my\name"
echo \strlen('hi'); // ruft die Funktion "strlen" auf
$a = \INI_ALL; // $a wird auf den Wert der Konstante "INI_ALL" gesetzt
?>
Wie wird ein Name wie mein\name
aufgelöst?
Namen, die einen Backslash beinhalten, aber nicht mit einem Backslash
beginnen, wie z. B. mein\name
, können auf zwei
verschiedene Arten aufgelöst werden.
Falls es einen Import-Ausdruck gibt, der einen Alias für einen anderen Namen
definiert, so dass dieser mein
heißen soll, dann wird dieser
Alias für das mein
in mein\name
angewandt.
Andernfalls wird der aktuelle Namespace vor mein\name
vorangestellt.
Beispiel #6 Qualifizierte Namen
<?php
namespace foo;
use blah\blah as foo;
$a = new my\name(); // erzeugt ein Objekt der Klasse "foo\my\name"
foo\bar::name(); // ruft die statische Methode "name"
// der Klasse "blah\blah\bar" auf
my\bar(); // ruft die Funktion "foo\my\bar" auf
$a = my\BAR; // setzt $a auf den Wert der Konstante "foo\my\BAR"
?>
Wie wird ein unqualifizierter Name wie name
aufgelöst?
Klassennamen, die keinen Backslash beinhalten, wie z. B.
name
, können auf zwei Arten aufgelöst werden.
Falls es einen Import-Ausdruck gibt, der einen Alias für einen anderen Namen
definiert, so dass dieser name
heißen soll, dann wird dieser
Alias angewandt.
Andernfalls wird der aktuelle Namespace name
vorangestellt.
Beispiel #7 Unqualifizierter Klassennamen
<?php
namespace foo;
use blah\blah as foo;
$a = new name(); // erzeugt ein Objekt der Klasse "foo\name"
foo::name(); // ruft die statische Methode "name" der Klasse "blah\blah" auf
?>
Wie wird ein unqualifizierter Funktions- oder Konstantenname wie
name
aufgelöst?
Funktions- oder Konstantennamen, die keinen Backslash beinhalten,
wie z. B. name
, können auf zwei verschiedene
Arten aufgelöst werden.
Zuerst wird der aktuelle Namespace dem name
vorangestellt.
Wenn die Konstante oder Funktion name
im aktuellen
Namensraum nicht existiert, so wird die globale Konstante oder
Funktion name
verwendet, wenn sie existiert.
Beispiel #8 Unqualifizierte Funktions- oder Konstantennamen
<?php
namespace foo;
use blah\blah as foo;
const FOO = 1;
function my() {}
function foo() {}
function sort(&$a)
{
\sort($a);
$a = array_flip($a);
return $a;
}
my(); // ruft "foo\my" auf
$a = strlen('hi'); // ruft die globale Funktion "strlen" auf, weil
// foo\strlen nicht existiert
$arr = array(1,3,2);
$b = sort($arr); // ruft die Funktion "foo\sort" auf
$c = foo(); // ruft die Funktion "foo\foo" auf - der Alias wird ignoriert
$a = FOO; // setzt $a auf den Wert der Konstante "foo\FOO" -
// der Alias wird ignoriert
$b = INI_ALL; // setzt $b auf den Wert der globalen Konstante "INI_ALL"
?>
Importierte Namen dürfen keine Konflikte mit Klassennamen
in der gleichen Datei erzeugen.
Die folgende Kombination von Skripten ist gültig:
Es gibt hier, trotzdem es eine Klasse MyClass
im Namespace
mein\zeug
gibt, keinen Namenskonflikt, weil die Definition
der Klasse MyClass
sich in einer anderen Datei befindet.
Das nächste Beispiel erzeugt hingegen einen fatal error wegen eines
Namenskonflikts, weil MyClass
in derselben Datei
definiert wird, die auch den use-Ausdruck beinhaltet.
Verschachtelte Namespaces sind nicht erlaubt.
PHP erlaubt das Verschachteln von Namespaces nicht.
Es ist jedoch leicht möglich, verschachtelte Namespaces
zu simulieren:
Dynamische Namespacenamen sollten den Backslash escapen.
Es ist wichtig zu bemerken, dass ein Backslash in Strings als Escape-Zeichen
verwendet wird und daher immer verdoppelt werden sollte, wenn er in einem
String verwendet wird. Andernfalls besteht das Risiko ungewollter
Auswirkungen:
Beispiel #9 Gefahren von Namespacenamen in Strings mit doppelten Anführungszeichen
<?php
$a = "gefaehrlicher\name"; // \n ist in doppelten Anführungszeichen
// ein Zeilenumbruch!
$obj = new $a;
$a = 'ueberhaupt\nicht\gefaehrlich'; // hier gibt es keine Probleme
$obj = new $a;
?>
Innerhalb eines Strings, der von einfachen Anführungszeichen umschlossen ist,
ist es deutlich ungefährlicher, die Backslash-Escape-Sequenz zu verwenden.
Es wird dennoch empfohlen, Backslashes in allen Strings zu escapen.
Zugriff auf undefinierte Konstanten mit Backslashes beendet das Skript
mit einem fatal error.
Jeder Zugriff auf eine Konstante mit unqualifiziertem Namen, wie
FOO
, wird eine Notice erzeugen, welche erklärt, dass
PHP angenommen hat, dass FOO
der Wert der
Konstante sei. Jede Konstante, qualifiziert oder vollständig
qualifiziert, deren Name einen Backslash enthält, wird einen
fatal error hervorrufen, wenn sie nicht gefunden wurde.
Beispiel #10 Undefinierte Konstanten
<?php
namespace bar;
$a = FOO; // notice - undefined constant "FOO" assumed "FOO";
$a = \FOO; // fatal error, undefined namespace constant FOO
$a = Bar\FOO; // fatal error, undefined namespace constant bar\Bar\FOO
$a = \Bar\FOO; // fatal error, undefined namespace constant Bar\FOO
?>
Die speziellen Konstanten null
, true
und false
können nicht
überschrieben werden.
Jeder Versuch, eine Konstante in einem Namespace zu definieren, die eine
der speziellen, eingebauten Konstanten ist, wird einen fatal error
hervorrufen.
Beispiel #11 Spezielle Konstanten
<?php
namespace bar;
const NULL = 0; // fatal error;
const true = 'stupid'; // ebenfalls fatal error;
// etc.
?>