-
Notifications
You must be signed in to change notification settings - Fork 79
/
Copy pathnamespaces.xml
1577 lines (1478 loc) · 57.1 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"?>
<!-- $Revision$ -->
<!-- EN-Revision: 874f7c1266d4e4f2e1e6c79b5fb48b590caa1197 Maintainer: takagi Status: ready -->
<!-- CREDITS: mumumu -->
<chapter xml:id="language.namespaces" xmlns="http://docbook.org/ns/docbook"
version="1.1">
<title>名前空間</title>
<sect1 xml:id="language.namespaces.rationale">
<title>名前空間の概要</title>
<titleabbrev>概要</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<simpara>
名前空間とは何でしょう? 広義の「名前空間」とは、項目をカプセル化するもののことです。
これは多くの場面で見られる抽象概念です。
たとえば、たいていの OS はディレクトリでファイルをグループ化します。
この場合、ディレクトリがその中のファイルの名前空間として機能しています。
具体的に言うと、<literal>foo.txt</literal> というファイルは
<literal>/home/greg</literal> と <literal>/home/other</literal>
の両方に存在することが可能ですが、それらふたつの
<literal>foo.txt</literal> を同じディレクトリに配置することはできません。
さらに、<literal>/home/greg</literal> ディレクトリの外から
<literal>foo.txt</literal> にアクセスするには、ディレクトリ名をファイル名の前につけて
<literal>/home/greg/foo.txt</literal> としなければなりません。
プログラミングの世界における名前空間も、この延長線上にあります。
</simpara>
<simpara>
PHP の世界では、名前空間は次のふたつの問題を解決するための手段として用意されています。
ライブラリやアプリケーションの作者が、
クラスや関数といった再利用可能なコード部品を作ろうとするときにこれらの問題にぶちあたることになります。
</simpara>
<para>
<orderedlist>
<listitem>
<simpara>
あなたが作成したコードと PHP の組み込みのクラス/関数/定数
あるいはサードパーティのクラス/関数/定数の名前が衝突する
</simpara>
</listitem>
<listitem>
<simpara>
最初の問題を解決するためには、Extra_Long_Names のような長い名前をつけなければならない
</simpara>
</listitem>
</orderedlist>
</para>
<simpara>
PHP の名前空間は、関連するクラスやインターフェイス、関数、そして定数をひとまとめにして扱うものです。
PHP の名前空間構文の例を見てみましょう。
</simpara>
<example>
<title>名前空間構文の例</title>
<programlisting role="php">
<![CDATA[
<?php
namespace my\name; // "名前空間の定義" を参照ください
class MyClass {}
function myfunction() {}
const MYCONST = 1;
$a = new MyClass;
$c = new \my\name\MyClass; // "グローバル空間" を参照ください
$a = strlen('hi'); // "名前空間の使用法: グローバル関数/定数への
// 移行" を参照ください
$d = namespace\MYCONST; // "namespace 演算子および __NAMESPACE__ 定数"
// を参照ください
$d = __NAMESPACE__ . '\MYCONST';
echo constant($d); // "名前空間および動的言語機能" を参照ください
?>
]]>
</programlisting>
</example>
<note>
<simpara>
名前空間の名前は、大文字小文字を区別しません。
</simpara>
</note>
<note>
<para>
名前空間の名前として <literal>PHP</literal> や これらで始まる名前
(<literal>PHP\Classes</literal> など) は
言語の内部で使うために予約されており、ユーザーのコードで使うべきではありません。
</para>
</note>
</sect1>
<sect1 xml:id="language.namespaces.definition">
<title>名前空間の定義</title>
<titleabbrev>名前空間</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
PHP のコードならなんでも名前空間に含めることができますが、
実際に名前空間の影響を受けるのはクラス (抽象クラスやトレイトを含む) とインターフェイス、関数、そして定数だけです。
</para>
<para>
名前空間を宣言するには、キーワード <literal>namespace</literal>
を使用します。名前空間を含むファイルでは、他のコードより前にファイルの先頭で名前空間を宣言しなければなりません。
ただし <xref linkend="control-structures.declare" /> キーワードは例外です。
<example>
<title>名前空間の宣言</title>
<programlisting role="php">
<![CDATA[
<?php
namespace MyProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
?>
]]>
</programlisting>
</example>
<note>
<simpara>
完全修飾名(つまり、バックスラッシュで始まる名前) は名前空間の宣言では許されません。
なぜなら、この構成要素は名前空間の相対名として解釈される式だからです。
</simpara>
</note>
名前空間の宣言より前に書くことが許されているコードは
<literal>declare</literal> 文のみです。ソースファイルのエンコーディングを定義するために使用します。
さらに、PHP コード以外であっても名前空間の宣言の前に記述することはできません (スペースも同様です)。
<example>
<title>名前空間の宣言</title>
<programlisting role="php">
<![CDATA[
<html>
<?php
namespace MyProject; // fatal error - namespace must be the first statement in the script
?>
]]>
</programlisting>
</example>
</para>
<para>
さらに、他の PHP の制御構造とは異なり、同一の名前空間を複数のファイルで定義することができます。
これにより、ひとつの名前空間の内容をファイルシステム上で分割することができます。
</para>
</sect1>
<sect1 xml:id="language.namespaces.nested">
<title>サブ名前空間の宣言</title>
<titleabbrev>サブ名前空間</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
ディレクトリやファイルと同様、PHP の名前空間においても名前空間の階層構造を指定することができます。
このようにして名前空間を定義します。
<example>
<title>階層つきの名前空間の宣言</title>
<programlisting role="php">
<![CDATA[
<?php
namespace MyProject\Sub\Level;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
?>
]]>
</programlisting>
</example>
上の例は、定数 <literal>MyProject\Sub\Level\CONNECT_OK</literal>
とクラス <literal>MyProject\Sub\Level\Connection</literal>、
そして関数 <literal>MyProject\Sub\Level\connect</literal> を作成します。
</para>
</sect1>
<sect1 xml:id="language.namespaces.definitionmultiple">
<title>同一ファイル内での複数の名前空間の定義</title>
<titleabbrev>同一ファイル内での複数の名前空間の定義</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
複数の名前空間を同一ファイル内で宣言することもあります。
この場合の構文は次の 2 通りです。
</para>
<para>
<example>
<title>シンプルな組み合わせ方式による複数の名前空間の宣言</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>
この構文は、複数の名前空間をひとつのファイルに含める場合の方法としてはお勧めしません。
かわりに、次の波括弧構文を使うことを推奨します。
</para>
<para>
<example>
<title>波括弧構文による複数の名前空間の宣言</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>
ただ、複数の名前空間をひとつのファイルに記述するようなコーディングはできるだけ避けるべきです。
主な使い道としては、複数の PHP スクリプトをひとつのファイルにまとめるときくらいでしょう。
</para>
<para>
名前空間に属さないグローバルなコードを名前空間つきのコードと組み合わせるときには、
波括弧構文しか使用できません。グローバルなコードは、名前空間の名前を指定しない
namespace 文で囲みます。たとえば次のようになります。
<example>
<title>複数の名前空間および名前空間に属さないコードの宣言</title>
<programlisting role="php">
<![CDATA[
<?php
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace { // グローバルコード
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>
]]>
</programlisting>
</example>
</para>
<para>
namespace の波括弧の外側に書くことができる PHP コードは、最初の declare 文だけです。
<example>
<title>複数の名前空間および名前空間に属さないコードの宣言</title>
<programlisting role="php">
<![CDATA[
<?php
declare(encoding='UTF-8');
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>
</sect1>
<sect1 xml:id="language.namespaces.basics">
<title>名前空間の使用法: 基本編</title>
<titleabbrev>基本編</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
名前空間の使い方についてあれこれ言う前に、まずは
PHP がどのようにしてコード中の要素の名前空間を知るのかを理解しておくことが重要です。
PHP の名前空間は、ファイルシステムにたとえて考えることができます。
たとえば、ファイルシステム内のファイルにアクセスするには次の 3 つの方法があります。
<orderedlist>
<listitem>
<simpara>
<literal>foo.txt</literal> のような相対ファイル名を使う。これは
<literal>currentdirectory/foo.txt</literal> と解釈されます。ここで、
<literal>currentdirectory</literal> は現在いるディレクトリを表します。したがって、カレントディレクトリが
<literal>/home/foo</literal> であった場合はこれは <literal>/home/foo/foo.txt</literal>
となります。
</simpara>
</listitem>
<listitem>
<simpara>
<literal>subdirectory/foo.txt</literal> のような相対パス名を使う。これは
<literal>currentdirectory/subdirectory/foo.txt</literal> と解釈されます。
</simpara>
</listitem>
<listitem>
<simpara>
<literal>/main/foo.txt</literal> のような絶対パス名を使う。これは
<literal>/main/foo.txt</literal> と解釈されます。
</simpara>
</listitem>
</orderedlist>
PHP の名前空間内の要素についても同じ理屈があてはまります。
たとえば、クラス名を参照するには次の 3 つの方法があります。
<orderedlist>
<listitem>
<simpara>
<literal>$a = new foo();</literal> あるいは
<literal>foo::staticmethod();</literal> のような非修飾名
あるいはプレフィックスなしのクラス名。
現在の名前空間が <literal>currentnamespace</literal> である場合、これは
<literal>currentnamespace\foo</literal> と解釈されます。
名前空間に属さないグローバルなコードにおいては、これは
<literal>foo</literal> と解釈されます。
</simpara>
<simpara>
注意: 修飾されていない関数や定数は、名前空間内にその関数や定数がなければ
グローバルな関数あるいは変数とみなされます。詳細は
<link linkend="language.namespaces.fallback">名前空間の使用法:
グローバルな関数/定数への移行</link> を参照ください。
</simpara>
</listitem>
<listitem>
<simpara>
<literal>$a = new subnamespace\foo();</literal> あるいは
<literal>subnamespace\foo::staticmethod();</literal> のような修飾名
あるいはプレフィックスつきクラス名。
現在の名前空間が <literal>currentnamespace</literal> である場合、これは
<literal>currentnamespace\subnamespace\foo</literal> と解釈されます。
名前空間に属さないグローバルなコードにおいては、これは
<literal>subnamespace\foo</literal> と解釈されます。
</simpara>
</listitem>
<listitem>
<simpara>
<literal>$a = new \currentnamespace\foo();</literal> あるいは
<literal>\currentnamespace\foo::staticmethod();</literal> のような完全修飾名
あるいはグローバルプレフィックス演算子つきのクラス名。
これは、常にコードで記述されたとおりの名前である
<literal>currentnamespace\foo</literal> と解釈されます。
</simpara>
</listitem>
</orderedlist>
</para>
<para>
これら 3 つの構文を実際のコードで使う例を次に示します。
<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() {}
}
/* 非修飾名 */
foo(); // Foo\Bar\foo 関数と解釈されます
foo::staticmethod(); // Foo\Bar\foo クラスの staticmethod メソッドと解釈されます
echo FOO; // 定数 Foo\Bar\FOO と解釈されます
/* 修飾名 */
subnamespace\foo(); // Foo\Bar\subnamespace\foo 関数と解釈されます
subnamespace\foo::staticmethod(); // Foo\Bar\subnamespace\foo クラスの
// staticmethod メソッドと解釈されます
echo subnamespace\FOO; // 定数 Foo\Bar\subnamespace\FOO と解釈されます
/* 完全修飾名 */
\Foo\Bar\foo(); // Foo\Bar\foo 関数と解釈されます
\Foo\Bar\foo::staticmethod(); // Foo\Bar\foo クラスの staticmethod メソッドと解釈されます
echo \Foo\Bar\FOO; // 定数 Foo\Bar\FOO と解釈されます
?>
]]>
</programlisting>
</informalexample>
</para>
<para>
グローバルなクラス、関数あるいは定数にアクセスするには、完全修飾名を使用して
<function>\strlen</function>、<classname>\Exception</classname> あるいは
\<constant>INI_ALL</constant> などとすることができます。
<example>
<title>グローバルなクラス、関数および定数への名前空間内からのアクセス</title>
<programlisting role="php">
<![CDATA[
<?php
namespace Foo;
function strlen() {}
const INI_ALL = 3;
class Exception {}
$a = \strlen('hi'); // グローバル関数 strlen をコールします
$b = \INI_ALL; // グローバル定数 INI_ALL にアクセスします
$c = new \Exception('error'); // グローバルクラス Exception のインスタンスを作成します
?>
]]>
</programlisting>
</example>
</para>
</sect1>
<sect1 xml:id="language.namespaces.dynamic">
<title>名前空間と動的言語機能</title>
<titleabbrev>名前空間と動的言語機能</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
PHP における名前空間の実装は、PHP 自身が動的プログラミング言語であるという性質に影響を受けています。
したがって、次の例のようなコードを名前空間を使って書き直すには
<example>
<title>要素への動的なアクセス</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; // classname::__construct と表示します
$b = 'funcname';
$b(); // funcname と表示します
echo constant('constname'), "\n"; // global と表示します
?>
]]>
</programlisting>
</example>
完全修飾名 (クラス名に名前空間プレフィックスをつけたもの) を使う必要があります。
動的なクラス名、関数名あるいは定数名においては修飾名と完全修飾名に差はないので、
先頭のバックスラッシュはなくてもかまいません。
<example>
<title>名前空間つき要素への動的なアクセス</title>
<programlisting role="php">
<![CDATA[
<?php
namespace namespacename;
class classname
{
function __construct()
{
echo __METHOD__,"\n";
}
}
function funcname()
{
echo __FUNCTION__,"\n";
}
const constname = "namespaced";
/* ダブルクォートを使う場合は "\\namespacename\\classname" としなければなりません */
$a = '\namespacename\classname';
$obj = new $a; // namespacename\classname::__construct と表示します
$a = 'namespacename\classname';
$obj = new $a; // これも namespacename\classname::__construct と表示します
$b = 'namespacename\funcname';
$b(); // namespacename\funcname と表示します
$b = '\namespacename\funcname';
$b(); // これも namespacename\funcname と表示します
echo constant('\namespacename\constname'), "\n"; // namespaced と表示します
echo constant('namespacename\constname'), "\n"; // これも namespaced と表示します
?>
]]>
</programlisting>
</example>
</para>
<para>
<link linkend="language.namespaces.faq.quote">
文字列中の名前空間名のエスケープに関する注意</link>
を読んでおくことを忘れないようにしましょう。
</para>
</sect1>
<sect1 xml:id="language.namespaces.nsconstants">
<title>namespace キーワードおよび __NAMESPACE__ 定数</title>
<titleabbrev>namespace キーワードおよび __NAMESPACE__</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
PHP には、現在の名前空間内の要素へのアクセスを抽象化するための方法が 2 通りあります。
マジック定数 <constant>__NAMESPACE__</constant> および <literal>namespace</literal>
キーワードがそれです。
</para>
<para>
<constant>__NAMESPACE__</constant> の値は文字列で、現在の名前空間の名前が格納されます。
名前空間に属さないグローバルなコードでは、この中身は空文字列となります。
<example>
<title>名前空間内のコードでの __NAMESPACE__ の例</title>
<programlisting role="php">
<![CDATA[
<?php
namespace MyProject;
echo '"', __NAMESPACE__, '"'; // "MyProject" と出力します
?>
]]>
</programlisting>
</example>
<example>
<title>グローバルなコードでの __NAMESPACE__ の例</title>
<programlisting role="php">
<![CDATA[
<?php
echo '"', __NAMESPACE__, '"'; // "" と出力します
?>
]]>
</programlisting>
</example>
<constant>__NAMESPACE__</constant> 定数は、動的に名前を作成する場合に便利です。
たとえば次のようになります。
<example>
<title>__NAMESPACE__ による動的な名前の作成</title>
<programlisting role="php">
<![CDATA[
<?php
namespace MyProject;
function get($classname)
{
$a = __NAMESPACE__ . '\\' . $classname;
return new $a;
}
?>
]]>
</programlisting>
</example>
</para>
<para>
<literal>namespace</literal> キーワードを使用すると、
現在の名前空間あるいはサブ名前空間内の要素を明示的に指定することができます。
これは、クラスにおける <literal>self</literal>
演算子と同じ意味合いのものです。
<example>
<title>名前空間内での namespace 演算子</title>
<programlisting role="php">
<![CDATA[
<?php
namespace MyProject;
use blah\blah as mine; // "名前空間の使用法: エイリアス/インポート" を参照ください
blah\mine(); // MyProject\blah\mine() 関数をコールします
namespace\blah\mine(); // MyProject\blah\mine() 関数をコールします
namespace\func(); // MyProject\func() 関数をコールします
namespace\sub\func(); // MyProject\sub\func() 関数をコールします
namespace\cname::method(); // MyProject\cname クラスのstaticメソッド "method" をコールします
$a = new namespace\sub\cname(); // MyProject\sub\cname クラスのオブジェクトのインスタンスを作成します
$b = namespace\CONSTANT; // 定数 MyProject\CONSTANT の値を $b に代入します
?>
]]>
</programlisting>
</example>
<example>
<title>グローバルコードでの namespace 演算子</title>
<programlisting role="php">
<![CDATA[
<?php
namespace\func(); // func() 関数をコールします
namespace\sub\func(); // sub\func() 関数をコールします
namespace\cname::method(); // cname クラスのstaticメソッド "method" をコールします
$a = new namespace\sub\cname(); // sub\cname クラスのオブジェクトのインスタンスを作成します
$b = namespace\CONSTANT; // 定数 CONSTANT の値を $b に代入します
?>
]]>
</programlisting>
</example>
</para>
</sect1>
<sect1 xml:id="language.namespaces.importing">
<title>名前空間の使用法: エイリアス/インポート</title>
<titleabbrev>エイリアス/インポート</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
外部の完全修飾名をエイリアスで参照したりインポートしたりする機能は、
名前空間において非常に重要なものです。
これは、Unix 系のファイルシステムでファイルやディレクトリへのシンボリックリンクを作成することに似ています。
</para>
<para>
PHP は定数、関数、クラス、インターフェイス、トレイト、列挙型(Enum)、名前空間のエイリアスやインポートをサポートしています。
</para>
<para>
エイリアス作成には <literal>use</literal> 演算子を使用します。
ここに、5 種類すべてのインポート方法の例を示します。
<example>
<title>use 演算子によるインポート/エイリアス</title>
<programlisting role="php">
<![CDATA[
<?php
namespace foo;
use My\Full\Classname as Another;
// これは use My\Full\NSname as NSname と同じです
use My\Full\NSname;
// グローバルクラスをインポートします
use ArrayObject;
// 関数をインポートします
use function My\Full\functionName;
// 関数のエイリアスを定義します
use function My\Full\functionName as func;
// 定数をインポートします
use const My\Full\CONSTANT;
$obj = new namespace\Another; // foo\Another クラスのオブジェクトのインスタンスを作成します
$obj = new Another; // My\Full\Classname クラスのオブジェクトのインスタンスを作成します
NSname\subns\func(); // My\Full\NSname\subns\func 関数をコールします
$a = new ArrayObject(array(1)); // ArrayObject クラスのオブジェクトのインスタンスを作成します
// "use ArrayObject" がなければ、foo\ArrayObject クラスのオブジェクトのインスタンスを作成することになります
func(); // 関数 My\Full\functionName を呼びます
echo CONSTANT; // 定数 My\Full\CONSTANT の値を表示します
?>
]]>
</programlisting>
</example>
名前空間つきの名前 (完全修飾形式の名前空間は区切り文字を含んだ
<literal>Foo\Bar</literal> のようなもので、グローバルな場合は区切り文字を含まない
<literal>FooBar</literal> のようになります)
では先頭のバックスラッシュは不要で、推奨されないことに注意しましょう。
インポートする名前は完全修飾形式でなければならず、
現在の名前空間からの相対指定で処理されることはないからです。
</para>
<para>
PHP では、複数の use 文を同一行に置くための便利なショートカットもサポートしています。
<example>
<title>use 演算子によるインポート/エイリアスで、複数の use 文を組み合わせる例</title>
<programlisting role="php">
<![CDATA[
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // My\Full\Classname クラスのオブジェクトのインスタンスを作成します
NSname\subns\func(); // My\Full\NSname\subns\func 関数をコールします
?>
]]>
</programlisting>
</example>
</para>
<para>
インポートはコンパイル時に行われるので、動的なクラス名、関数名や定数名には影響を及ぼしません。
<example>
<title>インポートと動的名</title>
<programlisting role="php">
<![CDATA[
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // My\Full\Classname クラスのオブジェクトのインスタンスを作成します
$a = 'Another';
$obj = new $a; // Another クラスのオブジェクトのインスタンスを作成します
?>
]]>
</programlisting>
</example>
</para>
<para>
さらにインポートの影響が及ぶのは非修飾名および修飾名のみです。
完全修飾名は絶対的なものであり、インポートの影響を受けることはありません。
<example>
<title>インポートと完全修飾名</title>
<programlisting role="php">
<![CDATA[
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // My\Full\Classname クラスのオブジェクトのインスタンスを作成します
$obj = new \Another; // Another クラスのオブジェクトのインスタンスを作成します
$obj = new Another\thing; // My\Full\Classname\thing クラスのオブジェクトのインスタンスを作成します
$obj = new \Another\thing; // Another\thing クラスのオブジェクトのインスタンスを作成します
?>
]]>
</programlisting>
</example>
</para>
<sect2 xml:id="language.namespaces.importing.scope">
<title>インポート時のスコープ規則</title>
<para>
<literal>use</literal> キーワードの宣言は、ファイル内の一番外側のスコープ (グローバルスコープ)
あるいは名前空間宣言の中で行わなければなりません。
これは、インポートが実行時ではなくコンパイル時に行われるためです。
ブロック内のスコープではインポートできません。
次の例は、<literal>use</literal> キーワードの間違った使い方を示すものです。
</para>
<para>
<example>
<title>間違ったインポートの例</title>
<programlisting role="php">
<![CDATA[
<?php
namespace Languages;
function toGreenlandic()
{
use Languages\Danish;
// ...
}
?>
]]>
</programlisting>
</example>
</para>
<note>
<para>
インポート規則はファイル単位のものです。つまり、インクルードされたファイルは
インクロード元の親ファイルのインポート規則を <emphasis>引き継ぎません</emphasis>。
</para>
</note>
</sect2>
<sect2 xml:id="language.namespaces.importing.group">
<title><literal>use</literal> 宣言のグループ化</title>
<para>
同じ &namespace; から複数のクラスや関数そして定数をインポートする際には、
それらをひとつの &use.namespace; にまとめることができます。
</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;
// 上記のコードは、グループ化されたuse宣言と同等です。
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>グローバル空間</title>
<titleabbrev>グローバル空間</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
名前空間の定義がない場合、すべてのクラスや関数の定義はグローバル空間に配置されます。
これは、名前空間に対応する前の PHP がサポートしていた空間です。
名前の先頭に <literal>\</literal> をつけると、
名前空間の内部からであってもグローバル空間の名前を指定することができます。
<example>
<title>グローバル空間を指定する方法</title>
<programlisting role="php">
<![CDATA[
<?php
namespace A\B\C;
/* この関数は A\B\C\fopen です */
function fopen() {
/* ... */
$f = \fopen(...); // グローバルな fopen をコールします
return $f;
}
?>
]]>
</programlisting>
</example>
</para>
</sect1>
<sect1 xml:id="language.namespaces.fallback">
<title>名前空間の使用法: グローバル関数/定数への移行</title>
<titleabbrev>グローバル関数/定数への移行</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
名前空間内で、PHP が未定義のクラス名や関数、定数に出会った場合、
それぞれに応じて異なる優先順位で解決を行います。
クラス名は、常に現在の名前空間での名前として解釈されます。
したがって、内部クラスあるいは名前空間に属さないクラスにアクセスするには
次のように完全修飾名で指定しなければなりません。
<example>
<title>名前空間内からのグローバルクラスへのアクセス</title>
<programlisting role="php">
<![CDATA[
<?php
namespace A\B\C;
class Exception extends \Exception {}
$a = new Exception('hi'); // $a は A\B\C\Exception クラスのオブジェクトです
$b = new \Exception('hi'); // $b は Exception クラスのオブジェクトです
$c = new ArrayObject; // fatal error, class A\B\C\ArrayObject not found
?>
]]>
</programlisting>
</example>
</para>
<para>
関数や定数の場合、名前空間内にその関数や定数が見つからなければ
PHP はグローバル関数/定数を探します。
<example>
<title>名前空間内からのグローバル関数/定数への移行</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"; // "45" と表示します
echo INI_ALL, "\n"; // "7" と表示します - グローバルの INI_ALL に移行しました
echo strlen('hi'), "\n"; // "1" と表示します
if (is_array('hi')) { // "is not array" と表示します
echo "is array\n";
} else {
echo "is not array\n";
}
?>
]]>
</programlisting>
</example>
</para>
</sect1>
<sect1 xml:id="language.namespaces.rules">
<title>名前解決のルール</title>
<titleabbrev>名前解決のルール</titleabbrev>
<?phpdoc print-version-for="namespaces"?>
<para>
名前解決のルールを説明するにあたって、いくつかの重要な定義を示しておきます。
<variablelist>
<title>名前空間名の定義</title>
<varlistentry>
<term>非修飾名</term>
<listitem>
<para>
これは名前空間区切り文字を含まない識別子で、<literal>Foo</literal> のようなものです。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>修飾名</term>
<listitem>
<para>
これは名前空間区切り文字を含む識別子で、<literal>Foo\Bar</literal> のようなものです。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>完全修飾名</term>
<listitem>
<para>
これは名前空間区切り文字を含む識別子のうち先頭が名前空間区切り文字で始まるもので、
<literal>\Foo\Bar</literal> のようなものです。名前空間 <literal>\Foo</literal>
も完全修飾名です。
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>相対名</term>
<listitem>
<para>
<literal>namespace\Foo\Bar</literal> のように、
<literal>namespace</literal> で始まる識別子です。
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
名前解決は、これらの解決ルールによって行われます。
<orderedlist>
<listitem>
<simpara>
完全修飾名は、先頭の名前空間区切り文字を除いた名前に常に解決されます。
たとえば、<literal>\A\B</literal> は <literal>A\B</literal> と解釈されます。
</simpara>
</listitem>
<listitem>
<simpara>
相対名は、<literal>namespace</literal> という名前を、
現在の名前空間に置き換えたものに常に解決されます。
現在の名前空間がグローバル名前空間だった場合、
<literal>namespace\</literal> 名前空間は取り除かれます。
たとえば、名前空間 <literal>X\Y</literal> の中にある
<literal>namespace\A</literal> は、
<literal>X\Y\A</literal> に解決されます。
グローバル名前空間の中にある同じ名前は、
<literal>A</literal> に解決されます。
</simpara>
</listitem>
<listitem>
<simpara>
修飾名の場合は、名前の最初の識別子を、
現在のクラス/名前空間のインポートテーブルに従って翻訳します。
たとえば、名前空間 <literal>A\B\C</literal> が
<literal>C</literal> としてインポートされた場合、
<literal>C\D\E</literal> という名前は、
<literal>A\B\C\D\E</literal> と翻訳されます。
</simpara>
</listitem>
<listitem>
<simpara>
修飾名の場合で、適用すべきインポートルールがない場合、
現在の名前空間が名前の先頭に付加されます。
たとえば、名前空間 <literal>A\B</literal> の中にある
<literal>C\D\E</literal> という名前は
<literal>A\B\C\D\E</literal> に解決されます。
</simpara>
</listitem>
<listitem>
<simpara>
非修飾名の場合、名前はそれぞれのシンボルタイプの
現在のインポートテーブルに従って翻訳されます。
これは、クラスのような名前は、クラス/名前空間のインポートテーブルに従って
翻訳されるし、関数名は、関数のインポートテーブルに従うし、
定数は定数のインポートテーブルに従うということになります。
たとえば、<literal>use A\B\C;</literal> の後に、
<literal>new C()</literal> のようなことをすると、
C は <literal>A\B\C()</literal> に解決されます。
同じように、<literal>use function A\B\foo;</literal>
の後に <literal>foo()</literal> のようなことをすると、
<literal>A\B\foo</literal> という名前に解決されます。
</simpara>
</listitem>
<listitem>
<simpara>
非修飾名について、適用すべきインポートルールが存在せず、
名前がクラスのようなシンボルを参照している場合、
現在の名前空間が先頭に付加されます。
たとえば、名前空間 <literal>A\B</literal> の内部にある
<literal>new C()</literal> は、
<literal>A\B\C</literal> という名前に解決されます。
</simpara>
</listitem>
<listitem>
<simpara>
非修飾名について、適用すべきインポートルールが存在せず、
名前が関数や定数を参照しており、
コードがグローバル名前空間の外に存在する場合は
名前は実行時に解決されます。
コードが名前空間 <literal>A\B</literal> の中にあると仮定すると、
関数 <literal>foo()</literal> のコールは、次のように解決されます。
</simpara>
<orderedlist>
<listitem>
<simpara>
まず現在の名前空間から関数
<literal>A\B\foo()</literal> を探します。
</simpara>