1
0
mirror of https://github.com/php/doc-de.git synced 2026-03-24 07:12:15 +01:00
Files
archived-doc-de/language/namespaces.xml
Martin Samesch 7ae9261232 Sync with EN
2025-10-09 21:31:17 +02:00

1653 lines
53 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: 1651836ff309efd14a795eff44ee51455f66c7d3 Maintainer: simp Status: ready -->
<!-- Reviewed: no -->
<chapter xml:id="language.namespaces" xmlns="http://docbook.org/ns/docbook" version="1.1">
<title>Namespaces</title>
<sect1 xml:id="language.namespaces.rationale">
<title>Übersicht über Namespaces</title>
<titleabbrev>Übersicht</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<simpara>
Was sind Namespaces? Im weitesten Sinne bieten Namespaces eine Möglichkeit,
verschiedene Gegenstände zu kapseln. Dies kann man als abstraktes Konzept
an vielen Dingen beobachten. In einem Betriebssystem dienen zum Beispiel
Verzeichnisse dazu, um zusammengehörige Dateien zu gruppieren, und dienen
als Namespace für die beinhalteten Dateien. In einem konkreten Beispiel
kann die Datei <literal>foo.txt</literal> sowohl im Verzeichnis
<literal>/home/greg</literal> als auch in <literal>/home/other</literal>
existieren, aber es können keine zwei Varianten der Datei
<literal>foo.txt</literal> im gleichen Verzeichnis existieren. Um auf die
Datei <literal>foo.txt</literal> von außerhalb des Verzeichnisses
<literal>/home/greg</literal> zuzugreifen, muss man zusätzlich dem
Verzeichnisnamen den Dateinamen und ein Trennzeichen voranstellen, um
<literal>/home/greg/foo.txt</literal> zu erhalten. Das gleiche Prinzip
streckt sich auf Namespaces in der Programmierwelt aus.
</simpara>
<simpara>
In der Welt von PHP wurden Namespaces entworfen, um zwei Probleme zu lösen,
auf die die Autoren von Bibliotheken und Anwendungen stoßen, wenn sie
wiederverwendbare Codeelemente wie Klassen und Funktionen entwickeln:
</simpara>
<para>
<orderedlist>
<listitem>
<simpara>
Namenskollisionen zwischen eigenem Code und internen
PHP-Klassen/Funktionen/Konstanten oder Klassen/Funktionen/Konstanten von
Drittanbietern.
</simpara>
</listitem>
<listitem>
<simpara>
Die Möglichkeit, einen Alias (oder einen Kurznamen) für Sehr_Lange_Namen
einzuführen, die geschaffen wurde, um das erste Problem zu umgehen.
Damit kann man die Lesbarkeit des Quellcodes erhöhen.
</simpara>
</listitem>
</orderedlist>
</para>
<simpara>
PHP-Namespaces bieten eine Möglichkeit, zusammengehörige Klassen,
Interfaces, Funktionen und Konstanten zusammenzufassen. Dies ist ein
Beispiel für die Namespace-Syntax in PHP:
</simpara>
<example>
<title>Beispiel für Namespace-Syntax</title>
<programlisting role="php">
<![CDATA[
<?php
namespace my\name; // siehe Abschnitt "Namespaces definieren"
class MyClass {}
function myfunction() {}
const MYCONST = 1;
$a = new MyClass;
$c = new \my\name\MyClass; // siehe Abschnitt "Globaler Namensraum"
$a = strlen('hi'); // siehe Abschnitt "Namespaces verwenden: Rückgriff auf
// globale Funktion/Konstante"
$d = namespace\MYCONST; // siehe Abschnitt "Namespace-Schlüsselwort und __NAMESPACE__-
// Konstante"
$d = __NAMESPACE__ . '\MYCONST';
echo constant($d); // siehe Abschnitt "Namespaces und dynamische Sprachfeatures"
?>
]]>
</programlisting>
</example>
<note>
<simpara>
Bei Namespace-Namen wird nicht zwischen Groß- und Kleinschreibung
unterschieden.
</simpara>
</note>
<note>
<para>
Der Namespace <literal>PHP</literal>, sowie zusammengesetzte Namen, die
mit dieser Bezeichnung beginnen (wie &zb; <literal>PHP\Classes</literal>),
sind zur internen Verwendung in der Sprache reserviert und sollten im
eigenen Programmcode nicht verwendet werden.
</para>
</note>
</sect1>
<sect1 xml:id="language.namespaces.definition">
<title>Namespaces definieren</title>
<titleabbrev>Namespaces</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
Obwohl jeder gültige PHP-Quellcode in Namespaces eingeschlossen werden kann,
werden nur die folgenden Arten von Code von Namespaces beeinflusst: Klassen
(inklusive abstrakter Klassen, Traits und Enums), Interfaces, Funktionen und
Konstanten.
</para>
<para>
Namespaces werden mit dem Schlüsselwort <literal>namespace</literal>
definiert. Eine Datei, die einen Namespace beinhaltet, muss den Namespace
am Anfang der Datei vor jeglichem anderen Code deklarieren - mit Ausnahme
des <xref linkend="control-structures.declare"/>-Schlüsselwortes.
<example>
<title>Einen einzelnen Namespace deklarieren</title>
<programlisting role="php">
<![CDATA[
<?php
namespace MyProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
?>
]]>
</programlisting>
</example>
<note>
<simpara>
Vollständig qualifizierte Namen (&dh; Namen, die mit einem
Rückwärtsschrägstrich beginnen) sind in Namensraumdeklarationen nicht
erlaubt, weil solche Konstrukte als relative Namensraumausdrücke
interpretiert werden.
</simpara>
</note>
Der einzige Quellcode, der vor einer Namespacedeklaration stehen darf,
ist der <literal>declare</literal>-Ausdruck, der die Kodierung der Quellcodedatei
definiert. Gleichzeitig darf kein Nicht-PHP-Code vor einer Namespacedeklaration
stehen - auch keine zusätzlichen Leerzeichen, Zeilenumbrüche oder Tabulatoren.
<example>
<title>Einen einzelnen Namespace deklarieren</title>
<programlisting role="php">
<![CDATA[
<html>
<?php
namespace MyProject; // fatal error - Namespace muss der erste Ausdruck im Skript sein
?>
]]>
</programlisting>
</example>
</para>
<para>
Zusätzlich darf - im Gegensatz zu anderen PHP-Konstrukten - der selbe
Namespace in mehreren Dateien definiert werden, womit man den Inhalt eines
Namespaces im Dateisystem aufteilen kann.
</para>
</sect1>
<sect1 xml:id="language.namespaces.nested">
<title>Unter-Namespaces deklarieren</title>
<titleabbrev>Unter-Namespaces</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
Ähnlich wie Verzeichnisse und Dateien hat ein PHP-Namespace auch die
Möglichkeit, eine Hierarchie von Namespacenamen zu beinhalten. Ein Namespace
kann also mit Unterebenen definiert werden:
<example>
<title>Einen einzelnen Namespace mit einer Hierarchie deklarieren</title>
<programlisting role="php">
<![CDATA[
<?php
namespace MyProject\Sub\Level;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
?>
]]>
</programlisting>
</example>
Das obige Beispiel erzeugt eine Konstante <literal>MyProject\Sub\Level\CONNECT_OK</literal>,
die Klasse <literal>MyProject\Sub\Level\Connection</literal> und die Funktion
<literal>MyProject\Sub\Level\connect</literal>.
</para>
</sect1>
<sect1 xml:id="language.namespaces.definitionmultiple">
<title>Mehrere Namespaces in derselben Datei definieren</title>
<titleabbrev>Mehrere Namespaces in derselben Datei definieren</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
Es können auch mehrere Namespaces in derselben Datei definiert werden. Es gibt
hierfür zwei mögliche Schreibweisen:
</para>
<para>
<example>
<title>Mehrere Namespaces definieren, einfache Kombinationssyntax</title>
<programlisting role="php">
<![CDATA[
<?php
namespace MyProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
namespace AnotherProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
?>
]]>
</programlisting>
</example>
</para>
<para>
Diese Syntax ist nicht die empfohlene Syntax, um mehrere Namespaces in einer
einzigen Datei zusammenzuführen. Stattdessen wird die geklammerte Syntax empfohlen.
</para>
<para>
<example>
<title>Mehrere Namespaces definieren, geklammerte Syntax</title>
<programlisting role="php">
<![CDATA[
<?php
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace AnotherProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
?>
]]>
</programlisting>
</example>
</para>
<para>
Es wird stark von der Programmierpraxis, mehrere Namespaces in einer Datei
zu definieren, abgeraten. Der wichtigste Einsatzzweck dieser Möglichkeit
ist es, mehrere PHP-Skripte in derselben Datei zusammenzuführen.
</para>
<para>
Um Code ohne Namensräume mit solchem mit Namensräumen zusammenzuführen, wird
nur die geklammerte Syntax unterstützt. Globaler Code sollte in einem
Namespace-Statement ohne Namespace eingeschlossen werden:
<example>
<title>Mehrere Namespaces und Code ohne Namespace deklarieren</title>
<programlisting role="php">
<![CDATA[
<?php
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace { // global code
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>
]]>
</programlisting>
</example>
</para>
<para>
Es darf kein PHP-Code außerhalb der Namespace-Klammern existieren, abgesehen
von einem beginnenden declare-Ausdruck.
<example>
<title>Mehrere Namespaces und Code ohne Namespace deklarieren</title>
<programlisting role="php">
<![CDATA[
<?php
declare(encoding='UTF-8');
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace { // globaler Code
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>
]]>
</programlisting>
</example>
</para>
</sect1>
<sect1 xml:id="language.namespaces.basics">
<title>Namespaces verwenden: Grundlagen</title>
<titleabbrev>Grundlagen</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
Bevor die Verwendung von Namespaces besprochen wird, ist es wichtig zu
verstehen, woher PHP weiß, welches Element mit Namespace vom Code
angefordert wird. Eine einfache Analogie kann zwischen PHP-Namensräumen und
einem Dateisystem gesehen werden. Es gibt drei Möglichkeiten, mit denen man
auf eine Datei in einem Dateisystem zugreifen kann:
<orderedlist>
<listitem>
<simpara>
Relative Dateinamen wie <literal>foo.txt</literal>. Dies wird zu
<literal>aktuellesVerzeichnis/foo.txt</literal> aufgelöst, wenn
<literal>aktuellesVerzeichnis</literal> das gerade geöffnete Verzeichnis
ist. Wenn also das aktuelle Verzeichnis <literal>/home/foo</literal>
ist, so wird dies als <literal>/home/foo/foo.txt</literal> aufgelöst.
</simpara>
</listitem>
<listitem>
<simpara>
Relative Pfade wie <literal>unterVerzeichnis/foo.txt</literal>. Dies wird zu
<literal>aktuellesVerzeichnis/unterVerzeichnis/foo.txt</literal> aufgelöst.
</simpara>
</listitem>
<listitem>
<simpara>
Absolute Pfadangaben wie <literal>/main/foo.txt</literal>. Dies wird zu
<literal>/main/foo.txt</literal> aufgelöst.
</simpara>
</listitem>
</orderedlist>
Das gleiche Prinzip kann auf Elemente mit Namespaces in PHP angewandt werden.
Zum Beispiel kann eine Klasse auf drei Arten angesprochen werden:
<orderedlist>
<listitem>
<simpara>
Unqualifizierte Namen oder ein Klassenname ohne Präfix, wie etwa
<literal>$a = new foo();</literal> oder
<literal>foo::staticmethod();</literal>. Falls der aktuelle Namespace
<literal>aktuellerNamespace</literal> ist, so wird dies zu
<literal>aktuellerNamespace\foo</literal> aufgelöst.
Ist der Code globaler Code ohne Namespaces, so wird dies zu
<literal>foo</literal> aufgelöst.
</simpara>
<simpara>
Es gibt eine Ausnahme hierzu: Unqualifizierte Namen für Funktionen und
Konstanten werden zu globalen Funktionen und Konstanten aufgelöst,
wenn die Funktion oder Konstante im Namespace nicht definiert ist.
Siehe auch <link linkend="language.namespaces.fallback">Namespaces verwenden:
Rückgriff auf globale Funktion/Konstante</link> für weitere Details.
</simpara>
</listitem>
<listitem>
<simpara>
Qualifizierte Namen oder ein Klassenname mit Präfix, wie etwa
<literal>$a = new unterNamespace\foo();</literal> oder
<literal>unterNamespace\foo::staticmethod();</literal>.
Wenn der aktuelle Namespace <literal>aktuellerNamespace</literal> ist, so
wird dies als
<literal>aktuellerNamespace\unterNamespace\foo</literal> verstanden.
Wenn der Code global und ohne Namespaces ist, so wird dies zu
<literal>unterNamespace\foo</literal> aufgelöst.
</simpara>
</listitem>
<listitem>
<simpara>
Vollständig qualifizierte Namen oder Namen mit globalem Präfixoperator wie
<literal>$a = new \aktuellerNamespace\foo();</literal> oder
<literal>\aktuellerNamespace\foo::staticmethod();</literal>.
Dies wird immer wörtlich wie der im Code angegebene Name verstanden, also
<literal>aktuellerNamespace\foo</literal>.
</simpara>
</listitem>
</orderedlist>
</para>
<para>
Hier ein Beispiel für die drei Schreibweisen in tatsächlichem Code:
<informalexample>
<simpara>file1.php</simpara>
<programlisting role="php">
<![CDATA[
<?php
namespace Foo\Bar\subnamespace;
const FOO = 1;
function foo() {}
class foo
{
static function staticmethod() {}
}
?>
]]>
</programlisting>
<simpara>file2.php</simpara>
<programlisting role="php">
<![CDATA[
<?php
namespace Foo\Bar;
include 'file1.php';
const FOO = 2;
function foo() {}
class foo
{
static function staticmethod() {}
}
/* Unqualifizierter Name */
foo(); // wird als Funktion Foo\Bar\foo aufgelöst
foo::staticmethod(); // wird als Klasse Foo\Bar\foo und Methode staticmethod aufgelöst
echo FOO; // gibt die Konstante Foo\Bar\FOO aus
/* Qualifizierter Name */
subnamespace\foo(); // wird als Funktion Foo\Bar\subnamespace\foo aufgelöst
subnamespace\foo::staticmethod(); // wird als Klasse Foo\Bar\subnamespace\foo und
// Methode staticmethod aufgelöst
echo subnamespace\FOO; // gibt die Konstante Foo\Bar\subnamespace\FOO aus
/* Vollständig qualifizierter Name */
\Foo\Bar\foo(); // wird als Funktion Foo\Bar\foo aufgelöst
\Foo\Bar\foo::staticmethod(); // wird als Klasse Foo\Bar\foo und Methode staticmethod aufgelöst
echo \Foo\Bar\FOO; // gibt die Konstante Foo\Bar\FOO aus
?>
]]>
</programlisting>
</informalexample>
</para>
<para>
Beachten Sie, dass für den Zugriff auf jede globale Klasse, Funktion oder
Konstante9 auch ein vollständig qualifizierter Name verwendet werden kann,
wie &zb; <function>\strlen</function>, <classname>\Exception</classname>
oder \<constant>INI_ALL</constant>.
<example>
<title>Zugriff auf globale Klassen, Funktionen und Konstanten aus einem Namespace</title>
<programlisting role="php">
<![CDATA[
<?php
namespace Foo;
function strlen() {}
const INI_ALL = 3;
class Exception {}
$a = \strlen('hi'); // ruft die globale Funktion strlen auf
$b = \INI_ALL; // greift auf die globale Konstante INI_ALL zu
$c = new \Exception('error'); // erzeugt eine Neue Instanz der globalen
// Klasse Exception
?>
]]>
</programlisting>
</example>
</para>
</sect1>
<sect1 xml:id="language.namespaces.dynamic">
<title>Namespaces und dynamische Sprachfeatures</title>
<titleabbrev>Namespaces und dynamische Sprachfeatures</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
Die Implementierung von Namespaces in PHP ist stark von seinen Eigenschaften
als Programmiersprache mit dynamischen Features beeinflusst. Man kann also den
folgenden Code in Code mit Namespaces umformen:
<example>
<title>Dynamischer Zugriff auf Elemente</title>
<simpara>example1.php:</simpara>
<programlisting role="php">
<![CDATA[
<?php
class classname
{
function __construct()
{
echo __METHOD__,"\n";
}
}
function funcname()
{
echo __FUNCTION__,"\n";
}
const constname = "global";
$a = 'classname';
$obj = new $a; // gibt classname::__construct aus
$b = 'funcname';
$b(); // gibt funcname aus
echo constant('constname'), "\n"; // gibt global aus
?>
]]>
</programlisting>
</example>
Um diesen Code umzuformen, muss man den vollständig qualifizierten Namen
(Klassenname mit namespace-Präfix) verwenden.
Beachten Sie, dass, weil es keinen Unterschied zwischen einem qualifizierten
und vollständig qualifizierten Namen innerhalb eines dynamischen Klassen-,
Funktions- oder Konstantennamen gibt, der führende Backslash nicht
notwendigerweise angegeben werden muss.
<example>
<title>Dynamischer Zugriff auf Elemente mit Namespace</title>
<programlisting role="php">
<![CDATA[
<?php
namespace namespacename;
class classname
{
function __construct()
{
echo __METHOD__,"\n";
}
}
function funcname()
{
echo __FUNCTION__,"\n";
}
const constname = "namespaced";
/* Wenn man doppelte Anführungszeichen verwendet,
muss "\\namespacename\\classname" verwendet werden */
$a = '\namespacename\classname';
$obj = new $a; // gibt namespacename\classname::__construct aus
$a = 'namespacename\classname';
$obj = new $a; // gibt ebenfalls namespacename\classname::__construct aus
$b = 'namespacename\funcname';
$b(); // gibt namespacename\funcname aus
$b = '\namespacename\funcname';
$b(); // gibt ebenfalls namespacename\funcname aus
echo constant('\namespacename\constname'), "\n"; // gibt namespaced aus
echo constant('namespacename\constname'), "\n"; // gibt ebenfalls namespaced aus
?>
]]>
</programlisting>
</example>
</para>
<para>
Bitte lesen Sie auch den <link linkend="language.namespaces.faq.quote">Hinweis zum
Escaping von Namespacenamen in Strings</link>.
</para>
</sect1>
<sect1 xml:id="language.namespaces.nsconstants">
<title>Das Schlüsselwort namespace und die magische Konstante __NAMESPACE__</title>
<titleabbrev>Schlüsselwort namespace und __NAMESPACE__</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
PHP unterstützt zwei Arten des abstrakten Zugriffs auf Elemente innerhalb eines
Namespaces, die magische Konstante <constant>__NAMESPACE__</constant> und das
Schlüsselwort <literal>namespace</literal>.
</para>
<para>
Der Wert von <constant>__NAMESPACE__</constant> ist ein String, der den Namen
des aktuellen Namespace beinhaltet. In globalem Code ohne Namespaces beinhaltet dies
einen leeren String.
<example>
<title>__NAMESPACE__-Beispiel, Code mit Namespace</title>
<programlisting role="php">
<![CDATA[
<?php
namespace MyProject;
echo '"', __NAMESPACE__, '"'; // gibt "MyProject" aus
?>
]]>
</programlisting>
</example>
<example>
<title>__NAMESPACE__-Beispiel, globaler Code</title>
<programlisting role="php">
<![CDATA[
<?php
echo '"', __NAMESPACE__, '"'; // gibt "" aus
?>
]]>
</programlisting>
</example>
Die Konstante <constant>__NAMESPACE__</constant> ist nützlich, um dynamische
Namen zu konstruieren, zum Beispiel:
<example>
<title>__NAMESPACE__ zur dynamischen Namenszusammensetzung verwenden</title>
<programlisting role="php">
<![CDATA[
<?php
namespace MyProject;
function get($classname)
{
$a = __NAMESPACE__ . '\\' . $classname;
return new $a;
}
?>
]]>
</programlisting>
</example>
</para>
<para>
Das Schlüsselwort <literal>namespace</literal> kann verwendet werden, um
explizit ein Element des aktuellen Namespaces oder eines untergeordneten
Namespaces anzufordern. Es ist das äquivalent der Namespaces zum
<literal>self</literal>-Operator für Klassen.
<example>
<title>Der namespace-Operator, innerhalb eines Namespace</title>
<programlisting role="php">
<![CDATA[
<?php
namespace MyProject;
use blah\blah as mine; // siehe "Namespaces verwenden: Aliase/Importieren"
blah\mine(); // ruft die Funktion MyProject\blah\mine() auf
namespace\blah\mine(); // ruft die Funktion MyProject\blah\mine() auf
namespace\func(); // ruft die Function MyProject\func() auf
namespace\sub\func(); // ruft die Function MyProject\sub\func() auf
namespace\cname::method(); // ruft die statische Methode "method" der Klasse MyProject\cname auf
$a = new namespace\sub\cname(); // erzeugt ein Objekt der Klasse MyProject\sub\cname
$b = namespace\CONSTANT; // weist den Wert der Konstante MyProject\CONSTANT $b zu
?>
]]>
</programlisting>
</example>
<example>
<title>Der namespace-Operator, in globalem Code</title>
<programlisting role="php">
<![CDATA[
<?php
namespace\func(); // ruft die Function func() auf
namespace\sub\func(); // ruft die Function sub\func() auf
namespace\cname::method(); // ruft die statische Methode "method" der Klasse cname auf
$a = new namespace\sub\cname(); // erzeugt ein Objekt der Klasse sub\cname
$b = namespace\CONSTANT; // weist den Wert der Konstante CONSTANT $b zu
?>
]]>
</programlisting>
</example>
</para>
</sect1>
<sect1 xml:id="language.namespaces.importing">
<title>Namespaces verwenden: Aliase/Importieren</title>
<titleabbrev>Aliase und Importieren</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
Die Möglichkeit, auf vollständig qualifizierte Namen mit einem Alias (Importieren)
zuzugreifen, ist ein wichtiges Feature von Namespaces. Dies ist ähnlich wie
die Möglichkeit von Unix-basierten Dateisystemen einen symbolischen Link auf eine
Datei oder ein Verzeichnis anzulegen.
</para>
<para>
PHP unterstützt das Vergeben von Aliasen (Importe) für Konstanten, Funktionen,
Klassen, Interfaces, Traits, Aufzählungen (Enums) und Namespaces.
</para>
<para>
Ein Alias wird mittels des <literal>use</literal>-Operators angelegt. Hier ein
Beispiel, welches alle fünf Arten von Importen zeigt:
<example>
<title>Aliase/Importieren mit dem use-Operator</title>
<programlisting role="php">
<![CDATA[
<?php
namespace foo;
use My\Full\Classname as Another;
// dies ist das gleiche wie use My\Full\NSname as NSname
use My\Full\NSname;
// importiert eine globale Klasse
use ArrayObject;
// Eine Funktion importieren
use function My\Full\functionName;
// Alias für eine Funktion
use function My\Full\functionName as func;
// Eine Konstante importieren
use const My\Full\CONSTANT;
$obj = new namespace\Another; // erzeugt ein Objekt der Klasse foo\Another
$obj = new Another; // erzeugt ein Objekt der Klasse My\Full\Classname
NSname\subns\func(); // ruft die Funktion My\Full\NSname\subns\func auf
$a = new ArrayObject(array(1)); // erzeugt ein Objekt der Klasse ArrayObject
// ohne das "use ArrayObject" wäre ein Objekt der Klasse foo\ArrayObject erzeugt worden
func(); // ruft die Funktion My\Full\functionName auf
echo CONSTANT; // Gibt den Wert von My\Full\CONSTANT aus
?>
]]>
</programlisting>
</example>
Beachten Sie, dass für Namen von Namespaces (vollständig qualifizierte Namespacenamen
mit einem Namensraumseparator, wie <literal>Foo\Bar</literal>, im Gegensatz zu
globalen Namen ohne Separator, wie <literal>FooBar</literal>) der führende
Backslash nicht notwendig und nicht empfohlen ist, weil importierte Namen vollständig
qualifiziert sein müssen und nicht relativ zum aktuellen Namespace verarbeitet
werden.
</para>
<para>
PHP unterstützt zusätzlich auch eine komfortable Kurzsyntax, mit der mehrere
use-Ausdrücke in der gleichen Zeile erscheinen können.
<example>
<title>Aliase/Importieren mit dem use-Operator, mehrere use-Ausdrücke kombiniert</title>
<programlisting role="php">
<![CDATA[
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // erzeugt ein Objekt der Klasse My\Full\Classname
NSname\subns\func(); // ruft die Funktion My\Full\NSname\subns\func auf
?>
]]>
</programlisting>
</example>
</para>
<para>
Importieren wird zur Kompilierungszeit ausgeführt und hat daher keinen Einfluss
auf dynamische Klassen-, Funktions- oder Konstantennamen.
<example>
<title>Importieren und dynamische Namen</title>
<programlisting role="php">
<![CDATA[
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // erzeugt ein Objekt der Klasse My\Full\Classname
$a = 'Another';
$obj = new $a; // erzeugt ein Objekt der Klasse Another
?>
]]>
</programlisting>
</example>
</para>
<para>
Zusätzlich beeinflusst das Importieren nur unqualifizierte und qualifizierte
Namen. Vollständig qualifizierte Namen sind absolut und werden von Importen
nicht beeinflusst.
<example>
<title>Importieren und vollständig qualifizierte Namen</title>
<programlisting role="php">
<![CDATA[
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // erzeugt ein Objekt der Klasse My\Full\Classname
$obj = new \Another; // erzeugt ein Objekt der Klasse Another
$obj = new Another\thing; // erzeugt ein Objekt der Klasse My\Full\Classname\thing
$obj = new \Another\thing; // erzeugt ein Objekt der Klasse Another\thing
?>
]]>
</programlisting>
</example>
</para>
<sect2 xml:id="language.namespaces.importing.scope">
<title>Gültigkeitsbereiche für Importe</title>
<para>
Das Schlüsselwort <literal>use</literal> muss im äußersten Gültigkeitsbereich
(dem globalen Gültigkeitsbereich) oder innerhalb einer Namespace-Deklaration
angegeben werden. Das ist darin begründet, dass Importe zur Kompilierungszeit
und nicht zur Laufzeit durchgeführt werden und daher nicht in einem anderen
Gültigkeitsbereich liegen dürfen. Das folgende Beispiel zeigt eine ungültige
Verwendung des <literal>use</literal>-Schlüsselwortes:
</para>
<para>
<example>
<title>Ungültige Importregel</title>
<programlisting role="php">
<![CDATA[
<?php
namespace Languages;
function toGreenlandic()
{
use Languages\Danish;
// ...
}
?>
]]>
</programlisting>
</example>
</para>
<note>
<para>
Importregeln sind auf Dateibasis gültig, das heißt eine eingebundene Datei
wird <emphasis>NICHT</emphasis> die Importregeln der einbindenden Datei erben.
</para>
</note>
</sect2>
<sect2 xml:id="language.namespaces.importing.group">
<title>Gruppierte <literal>use</literal> Deklarationen</title>
<para>
Klassen, Funktionen und Konstanten, die aus dem
gleichen Namespace importiert werden, in einer einzigen &use.namespace;
Anweisung gruppiert werden.
</para>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;
use function some\namespace\fn_a;
use function some\namespace\fn_b;
use function some\namespace\fn_c;
use const some\namespace\ConstA;
use const some\namespace\ConstB;
use const some\namespace\ConstC;
// gleichbedeutend zu folgender gruppierter Use-Deklaration
use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};
]]>
</programlisting>
</informalexample>
</sect2>
</sect1>
<sect1 xml:id="language.namespaces.global">
<title>Globaler Namensraum</title>
<titleabbrev>Globaler Namensraum</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
Ohne die Definition eines Namespace werden alle Klassen- und
Funktionsdefinitionen im globalen Namensraum platziert, so wie dies
auch in PHP geschah bevor Namespaces unterstützt wurden.
Wenn man dem Namen ein <literal>\</literal> voranstellt, so
spezifiziert man, dass der Name dem globalen Namensraum angehört,
auch wenn man sich im Kontext eines Namensraumes befindet.
<example>
<title>Verwenden der Spezifikation des globalen Namensraumes</title>
<programlisting role="php">
<![CDATA[
<?php
namespace A\B\C;
/* Diese Funktion ist A\B\C\fopen */
function fopen() {
/* ... */
$f = \fopen(...); // globale Funktion fopen aufrufen
return $f;
}
?>
]]>
</programlisting>
</example>
</para>
</sect1>
<sect1 xml:id="language.namespaces.fallback">
<title>Namespaces verwenden: Rückgriff auf den globalen Namespace für Funktionen und Konstanten</title>
<titleabbrev>Rückgriff auf den globalen Namespace</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
Wenn PHP innerhalb eines Namespace auf einen unqualifizierten Namen
für einen Klassen-, Funktions- oder Konstantennamen trifft, so werden diese
mit unterschiedlichen Prioritäten aufgelöst. Klassennamen werden immer
auf den aktuellen Namespace aufgelöst. Um also auf interne Klassen oder
Benutzerklassen ohne Namespace zuzugreifen, muss man diese mit ihrem
vollständig qualifizierten Namen ansprechen:
<example>
<title>Zugriff auf globale Klasse innerhalb eines Namespace</title>
<programlisting role="php">
<![CDATA[
<?php
namespace A\B\C;
class Exception extends \Exception {}
$a = new Exception('hi'); // $a ist ein Objekt der Klasse A\B\C\Exception
$b = new \Exception('hi'); // $b ist ein Objekt der Klasse Exception
$c = new ArrayObject; // fatal error, die Klasse A\B\C\ArrayObject konnte
// nicht gefunden werden
?>
]]>
</programlisting>
</example>
</para>
<para>
Für Funktionen und Konstanten wird PHP auf globale Funktionen oder
Konstanten zurückgreifen, wenn eine Funktion oder Konstante im
Namespace nicht existiert.
<example>
<title>Rückgriff auf globale Funktionen/Konstanten innerhalb eines Namespace</title>
<programlisting role="php">
<![CDATA[
<?php
namespace A\B\C;
const E_ERROR = 45;
function strlen($str)
{
return \strlen($str) - 1;
}
echo E_ERROR, "\n"; // gibt "45" aus
echo INI_ALL, "\n"; // gibt "7" aus - Rückgriff auf globale INI_ALL
echo strlen('hi'), "\n"; // gibt "1" aus
if (is_array('hi')) { // gibt "ist kein Array" aus
echo "ist Array\n";
} else {
echo "ist kein Array\n";
}
?>
]]>
</programlisting>
</example>
</para>
</sect1>
<sect1 xml:id="language.namespaces.rules">
<title>Regeln für Namensauflösung</title>
<titleabbrev>Regeln für Namensauflösung</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
Hier einige wichtige Definitionen für die Zwecke der Namensauflösungsregeln:
<variablelist>
<title>Namespace-Namen-Definitionen</title>
<varlistentry>
<term>Unqualifizierter Name</term>
<listitem>
<para>
Dies ist ein Bezeichner ohne einen Namespaceseparator, &zb;
<literal>Foo</literal>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Qualifizierter Name</term>
<listitem>
<para>
Dies ist ein Bezeichner mit einem Namespaceseparator, &zb;
<literal>Foo\Bar</literal>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Vollständig qualifizierter Name</term>
<listitem>
<para>
Dies ist ein Bezeichner mit einem Namespaceseparator, der mit einem
Namespaceseparator beginnt, &zb; <literal>\Foo\Bar</literal>. Der
Namespace <literal>namespace\Foo</literal> ist ebenfalls ein
vollständig qualifizierter Name.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Relativer Name</term>
<listitem>
<para>
Dies ist ein Bezeichner, der mit <literal>namespace</literal> beginnt, wie
etwa <literal>namespace\Foo\Bar</literal>.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
Namen werden gemäß den folgenden Regeln aufgelöst:
<orderedlist>
<listitem>
<simpara>
Vollständig qualifizierte Namens werden immer zu dem Namen ohne führenden
Namensraumtrenner aufgelöst. <literal>\A\B</literal> wird
&zb; zu <literal>A\B</literal> aufgelöst.
</simpara>
</listitem>
<listitem>
<simpara>
Relative Namen werden immer zu dem Namen aufgelöst, in dem <literal>namespace</literal>
durch den aktuellen Namensraum ersetzt wurde. Taucht der Namen im globalen
Geltungsbereich auf, wird das <literal>namespace\</literal>-Präfix entfernt.
Beispielsweise wird <literal>namespace\A</literal> innerhalb des Namensraums
<literal>X\Y</literal> zu <literal>X\Y\A</literal> aufgelöst. Derselbe Name
im globalen Geltungsbereich wird zu <literal>A</literal> aufgelöst.
</simpara>
</listitem>
<listitem>
<simpara>
Für qualifizierte Namen wird das erste Segment des Namens gemäß der aktuellen
Klassen-/Namensraum-Importtabelle übersetzt. Wird beispielsweise der Namensraum
<literal>A\B\C</literal> als <literal>C</literal> importiert, wird der Name
<literal>C\D\E</literal> zu <literal>A\B\C\D\E</literal> übersetzt.
</simpara>
</listitem>
<listitem>
<simpara>
Wenn für qualifizierte Namen keine Importregel zutrifft, wird der aktuelle Namensraum
dem Namen vorangestellt. Beispielsweise wird der Name <literal>C\D\E</literal>
innerhalb des Namensraums <literal>A\B</literal> zu <literal>A\B\C\D\E</literal>
aufgelöst.
</simpara>
</listitem>
<listitem>
<simpara>
Für unqualifizierte Namen wird der Name gemäß der aktuellen Importtabelle für
die betreffende Symboltabelle übersetzt. Das bedeutet, dass klassenartige
Namen gemäß der Klassen-/Namensraum-Importtabelle, Funktionsnamen gemäß der
Funktions-Importtabelle und Konstantennamen gemäß der Konstanten-Importtabelle
übersetzt werden. Beispielsweise wird nach <literal>use A\B\C;</literal> eine
Verwendung wie etwa <literal>new C()</literal> zum Namen <literal>A\B\C()</literal>
aufgelöst. Analog wird nach <literal>use function A\B\foo;</literal> eine
Verwendung wie etwa <literal>foo()</literal> zum Namen <literal>A\B\foo</literal>
aufgelöst.
</simpara>
</listitem>
<listitem>
<simpara>
Wenn für unqualifizierte Namen keine Importregel zutrifft, und sich der Name
auf ein klassenartiges Symbol bezieht, wird der aktuelle Namensraum vorangestellt.
Beispielsweise wird <literal>new C()</literal> innerhalb des Namensraums
<literal>A\B</literal> zum Namen <literal>A\B\C</literal> aufgelöst.
</simpara>
</listitem>
<listitem>
<simpara>
Wenn für unqualifizierte Namen keine Importregel zutrifft, und sich der Name
auf eine Funktion oder Konstante bezieht, und der Code sich außerhalb des
globalen Geltungsbereichs befindet, wird der Name zur Laufzeit aufgelöst.
Angenommen der Code befindet sich im Namensraum <literal>A\B</literal>, wird
im folgenden erläutert, wie der Aufruf einer Funktion <literal>foo()</literal>
aufgelöst wird:
</simpara>
<orderedlist>
<listitem>
<simpara>
Zuerst wird nach der Funktion im aktuellen Namespace gesucht:
<literal>A\B\foo()</literal>.
</simpara>
</listitem>
<listitem>
<simpara>
Es wird versucht, die Funktion <literal>foo()</literal> im
<emphasis>globalen</emphasis> Namensraum zu finden und aufzurufen.
</simpara>
</listitem>
</orderedlist>
</listitem>
</orderedlist>
</para>
<example>
<title>Illustration der Namensauflösung</title>
<programlisting role="php">
<![CDATA[
<?php
namespace A;
use B\D, C\E as F;
// Funktionsaufrufe
foo(); // versucht zuerst die Funktion "foo" im Namespace "A" aufzurufen
// danach wird die globale Funktion "foo" aufgerufen
\foo(); // ruft die Funktion "foo" im globalen Namensraum auf
my\foo(); // ruft die Funktion "foo" im Namespace "A\my" auf
F(); // versucht zuerst die Funktion "F" im Namespace "A" aufzurufen,
// danach wird die globale Funktion "F" aufgerufen
// Klassenreferenzen
new B(); // erzeugt ein Objekt der Klasse "B" im Namespace "A"
// wenn diese Klasse nicht bekannt ist, so wird versucht per
// Autoload die Klasse "A\B" zu laden
new D(); // gemäß den Importregeln wird ein Objekt der Klasse "D"
// aus dem Namenspace "B" erzeugt
// wenn diese Klasse nicht bekannt ist, so wird versucht per
// Autoload die Klasse "B\D" zu laden
new F(); // gemäß den Importregeln wird ein Objekt der Klasse "E"
// aus dem Namespace "C" erzeugt
// wenn diese Klasse nicht bekannt ist, so wird versucht per
// Autoload die Klasse "C\E" zu laden
new \B(); // erzeugt ein Objekt der Klasse "B" aus dem globalen Namensraum
// wenn diese Klasse nicht bekannt ist, so wird versucht per
// Autoload die Klasse "B" zu laden
new \D(); // erzeugt ein Objekt der Klasse "D" aus dem globalen Namensraum
// wenn diese Klasse nicht bekannt ist, so wird versucht per
// Autoload die Klasse "D" zu laden
new \F(); // erzeugt ein Objekt der Klasse "F" aus dem globalen Namensraum
// wenn diese Klasse nicht bekannt ist, so wird versucht per
// Autoload die Klasse "F" zu laden
// statische Methoden und Funktionen mit Namespace aus anderen Namespaces
B\foo(); // ruft die Funktion "foo" aus dem Namensraum "A\B" auf
B::foo(); // ruft die Methode "foo" der Klasse "B" im Namensraum "A" auf
// wenn die Klasse "A\B" nicht bekannt ist, so wird versucht
// die Klasse "A\B" mittels Autoload zu laden
D::foo(); // ruft gemäß den Importregeln die Methode "foo" der Klasse "D"
// im Namensraum "B" auf
// wenn die Klasse "B\D" nicht bekannt ist, so wird versucht
// die Klasse "B\D" mittels Autoload zu laden
\B\foo(); // ruft die Funktion "foo" im Namespace "B" auf
\B::foo(); // ruft die Methode "foo" der Klasse "B" im
// globalen Namensraum auf
// wenn die Klasse "B" nicht bekannt ist, so wird versucht
// die Klasse "B" mittels Autoload zu laden
// statische Methoden und Funktionen mit Namespace aus den gleichen Namespaces
A\B::foo(); // ruft die Methode "foo" der Klasse "B" aus dem Namespace "A\A" auf
// wenn die Klasse "A\A\B" nicht bekannt ist, so wird
// versucht die Klasse "A\A\B" mittels Autoload zu laden
\A\B::foo(); // ruft die Methode "foo" der Klasse "B" aus dem Namespace "A" auf
// wenn die Klasse "A\B" nicht bekannt ist, so wird
// versucht die Klasse "A\B" mittels Autoload zu laden
?>
]]>
</programlisting>
</example>
</sect1>
<sect1 xml:id="language.namespaces.faq">
<title>FAQ: Dinge, die Sie über Namespaces wissen sollten</title>
<titleabbrev>FAQ</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
Diese häufig gestellten Fragen (FAQ) wurden in zwei Abschnitte aufgeteilt:
allgemeine Fragen und einige Implementierungsdetails, deren
vollständiges Verständnis hilfreich sein kann.
</para>
<para>
Zuerst die allgemeinen Fragen.
<orderedlist>
<listitem>
<simpara>
<link linkend="language.namespaces.faq.shouldicare">Wenn ich keine Namespaces
verwende, sollte mich das alles hier überhaupt interessieren?</link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="language.namespaces.faq.globalclass">Wie verwende ich interne
oder globale Klassen in einem Namespace?</link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="language.namespaces.faq.innamespace">Wie verwende ich Klassen,
Funktionen oder Konstanten mit Namespaces in ihrem eigenen Namespace?</link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="language.namespaces.faq.full">
Wie wird ein Name wie <literal>\mein\name</literal> oder
<literal>\name</literal> aufgelöst?
</link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="language.namespaces.faq.qualified">Wie wird ein Name
wie <literal>mein\name</literal> aufgelöst?</link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="language.namespaces.faq.shortname1">Wie wird ein
unqualifizierter Name wie <literal>name</literal> aufgelöst?</link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="language.namespaces.faq.shortname2">Wie wird ein
unqualifizierter Funktions- oder Konstantenname wie
<literal>name</literal> aufgelöst?</link>
</simpara>
</listitem>
</orderedlist>
</para>
<para>
Es gibt einige Implementierungsdetails von Namespaces, deren
Verständnis hilfreich ist.
<orderedlist>
<listitem>
<simpara>
<link linkend="language.namespaces.faq.conflict">Importierte Namen
dürfen keine Konflikte mit Klassennamen in der gleichen Datei erzeugen.</link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="language.namespaces.faq.nested">Verschachtelte
Namespaces sind nicht erlaubt.</link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="language.namespaces.faq.quote">Dynamische Namespacenamen
sollten den Backslash escapen.</link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="language.namespaces.faq.constants">Zugriff auf
undefinierte Konstanten mit Backslashes beendet das Skript mit
einem fatal error.</link>
</simpara>
</listitem>
<listitem>
<simpara>
<link linkend="language.namespaces.faq.builtinconst">Die speziellen Konstanten
&null;, &true; und &false; können nicht überschrieben werden.</link>
</simpara>
</listitem>
</orderedlist>
</para>
<sect2 xml:id="language.namespaces.faq.shouldicare">
<title>Wenn ich keine Namespaces verwende, sollte mich das alles
hier überhaupt interessieren?</title>
<para>
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:
</para>
<para>
<example>
<title>Zugriff auf globale Klassen außerhalb eines Namespace</title>
<programlisting role="php">
<![CDATA[
<?php
$a = new \stdClass;
?>
]]>
</programlisting>
</example>
</para>
<para>
Dies ist äquivalent zu:
</para>
<para>
<example>
<title>Zugriff auf globale Klassen außerhalb eines Namespace</title>
<programlisting role="php">
<![CDATA[
<?php
$a = new stdClass;
?>
]]>
</programlisting>
</example>
</para>
</sect2>
<sect2 xml:id="language.namespaces.faq.globalclass">
<title>Wie verwende ich interne oder globale Klassen in einem Namespace?</title>
<para>
<example>
<title>Zugriff auf interne Klassen in Namespaces</title>
<programlisting role="php">
<![CDATA[
<?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 {}
?>
]]>
</programlisting>
</example>
</para>
</sect2>
<sect2 xml:id="language.namespaces.faq.innamespace">
<title>
Wie verwende ich Klassen, Funktionen oder Konstanten mit Namespaces
in ihrem eigenen Namespace?
</title>
<para>
<example>
<title>Zugriff auf interne Klassen, Funktionen oder Konstanten in Namespaces</title>
<programlisting role="php">
<![CDATA[
<?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;
?>
]]>
</programlisting>
</example>
</para>
</sect2>
<sect2 xml:id="language.namespaces.faq.full">
<title>
Wie wird ein Name wie <literal>\mein\name</literal> oder
<literal>\name</literal> aufgelöst?
</title>
<para>
Namen, die mit einem <literal>\</literal> beginnen, werden immer
zu exakt dem aufgelöst wie sie aussehen. <literal>\mein\name</literal>
ist also tatsächlich <literal>\mein\name</literal> und
<literal>\Exception</literal> ist <literal>Exception</literal>.
<example>
<title>Vollständig qualifizierte Namen</title>
<programlisting role="php">
<![CDATA[
<?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
?>
]]>
</programlisting>
</example>
</para>
</sect2>
<sect2 xml:id="language.namespaces.faq.qualified">
<title>Wie wird ein Name wie <literal>mein\name</literal> aufgelöst?</title>
<para>
Namen, die einen Backslash beinhalten, aber nicht mit einem Backslash
beginnen, wie &zb; <literal>mein\name</literal>, können auf zwei
verschiedene Arten aufgelöst werden.
</para>
<para>
Falls es einen Import-Ausdruck gibt, der einen Alias für einen anderen Namen
definiert, so dass dieser <literal>mein</literal> heißen soll, dann wird dieser
Alias für das <literal>mein</literal> in <literal>mein\name</literal> angewandt.
</para>
<para>
Andernfalls wird der aktuelle Namespace vor <literal>mein\name</literal>
vorangestellt.
</para>
<para>
<example>
<title>Qualifizierte Namen</title>
<programlisting role="php">
<![CDATA[
<?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"
?>
]]>
</programlisting>
</example>
</para>
</sect2>
<sect2 xml:id="language.namespaces.faq.shortname1">
<title>Wie wird ein unqualifizierter Name wie <literal>name</literal> aufgelöst?</title>
<para>
Klassennamen, die keinen Backslash beinhalten, wie &zb;
<literal>name</literal>, können auf zwei Arten aufgelöst werden.
</para>
<para>
Falls es einen Import-Ausdruck gibt, der einen Alias für einen anderen Namen
definiert, so dass dieser <literal>name</literal> heißen soll, dann wird dieser
Alias angewandt.
</para>
<para>
Andernfalls wird der aktuelle Namespace <literal>name</literal> vorangestellt.
</para>
<para>
<example>
<title>Unqualifizierter Klassennamen</title>
<programlisting role="php">
<![CDATA[
<?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
?>
]]>
</programlisting>
</example>
</para>
</sect2>
<sect2 xml:id="language.namespaces.faq.shortname2">
<title>
Wie wird ein unqualifizierter Funktions- oder Konstantenname wie
<literal>name</literal> aufgelöst?
</title>
<para>
Funktions- oder Konstantennamen, die keinen Backslash beinhalten,
wie &zb; <literal>name</literal>, können auf zwei verschiedene
Arten aufgelöst werden.
</para>
<para>
Zuerst wird der aktuelle Namespace dem <literal>name</literal> vorangestellt.
</para>
<para>
Wenn die Konstante oder Funktion <literal>name</literal> im aktuellen
Namensraum nicht existiert, so wird die globale Konstante oder
Funktion <literal>name</literal> verwendet, wenn sie existiert.
</para>
<para>
<example>
<title>Unqualifizierte Funktions- oder Konstantennamen</title>
<programlisting role="php">
<![CDATA[
<?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"
?>
]]>
</programlisting>
</example>
</para>
</sect2>
<sect2 xml:id="language.namespaces.faq.conflict">
<title>Importierte Namen dürfen keine Konflikte mit Klassennamen
in der gleichen Datei erzeugen.
</title>
<para>
Die folgende Kombination von Skripten ist gültig:
<informalexample>
<simpara>file1.php</simpara>
<programlisting role="php">
<![CDATA[
<?php
namespace mein\zeug;
class MyClass {}
?>
]]>
</programlisting>
<simpara>anderes.php</simpara>
<programlisting role="php">
<![CDATA[
<?php
namespace anderes;
class Ding {}
?>
]]>
</programlisting>
<simpara>file2.php</simpara>
<programlisting role="php">
<![CDATA[
<?php
namespace mein\zeug;
include 'file1.php';
include 'anderes.php';
use anderes\Ding as MyClass;
$a = new MyClass; // erzeugt ein Objekt der Klasse "Ding"
// aus dem Namespace "anderes"
?>
]]>
</programlisting>
</informalexample>
</para>
<para>
Es gibt hier, trotzdem es eine Klasse <literal>MyClass</literal> im Namespace
<literal>mein\zeug</literal> gibt, keinen Namenskonflikt, weil die Definition
der Klasse <literal>MyClass</literal> sich in einer anderen Datei befindet.
Das nächste Beispiel erzeugt hingegen einen fatal error wegen eines
Namenskonflikts, weil <literal>MyClass</literal> in derselben Datei
definiert wird, die auch den use-Ausdruck beinhaltet.
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
namespace mein\zeug;
use anderes\Ding as MyClass;
class MyClass {} // fatal error: Konflikt zwischen MyClass und import-Ausdruck
$a = new MyClass;
?>
]]>
</programlisting>
</informalexample>
</para>
</sect2>
<sect2 xml:id="language.namespaces.faq.nested">
<title>Verschachtelte Namespaces sind nicht erlaubt.</title>
<para>
PHP erlaubt das Verschachteln von Namespaces nicht.
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
namespace mein\zeug {
namespace verschachtelt {
class foo {}
}
}
?>
]]>
</programlisting>
</informalexample>
Es ist jedoch leicht möglich, verschachtelte Namespaces
zu simulieren:
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
namespace mein\zeug\verschachtelt {
class foo {}
}
?>
]]>
</programlisting>
</informalexample>
</para>
</sect2>
<sect2 xml:id="language.namespaces.faq.quote">
<title>Dynamische Namespacenamen sollten den Backslash escapen.</title>
<para>
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:
<example>
<title>Gefahren von Namespacenamen in Strings mit doppelten Anführungszeichen</title>
<programlisting role="php">
<![CDATA[
<?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;
?>
]]>
</programlisting>
</example>
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.
</para>
</sect2>
<sect2 xml:id="language.namespaces.faq.constants">
<title>Zugriff auf undefinierte Konstanten mit Backslashes beendet das Skript
mit einem fatal error.</title>
<para>
Jeder Zugriff auf eine Konstante mit unqualifiziertem Namen, wie
<literal>FOO</literal>, wird eine Notice erzeugen, welche erklärt, dass
PHP angenommen hat, dass <literal>FOO</literal> 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.
<example>
<title>Undefinierte Konstanten</title>
<programlisting role="php">
<![CDATA[
<?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
?>
]]>
</programlisting>
</example>
</para>
</sect2>
<sect2 xml:id="language.namespaces.faq.builtinconst">
<title>Die speziellen Konstanten &null;, &true; und &false; können nicht
überschrieben werden.</title>
<para>
Jeder Versuch, eine Konstante in einem Namespace zu definieren, die eine
der speziellen, eingebauten Konstanten ist, wird einen fatal error
hervorrufen.
<example>
<title>Spezielle Konstanten</title>
<programlisting role="php">
<![CDATA[
<?php
namespace bar;
const NULL = 0; // fatal error;
const true = 'stupid'; // ebenfalls fatal error;
// etc.
?>
]]>
</programlisting>
</example>
</para>
</sect2>
</sect1>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->