-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathnamespaces.xml
1652 lines (1554 loc) · 53.3 KB
/
namespaces.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: f4f96ef8b2a95283c92ea2183fe1dedf06f3ad22 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 und Traits), 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