mirror of
https://github.com/php/doc-de.git
synced 2026-03-24 07:12:15 +01:00
1653 lines
53 KiB
XML
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
|
|
-->
|