名前解決のルール
(PHP 5 >= 5.3.0)
名前解決のルールを説明するにあたって、いくつかの重要な定義を示しておきます。
-
名前空間名の定義
- 非修飾名
-
これは名前空間区切り文字を含まない識別子で、Foo のようなものです。
- 修飾名
-
これは名前空間区切り文字を含む識別子で、Foo\Bar のようなものです。
- 完全修飾名
-
これは名前空間区切り文字を含む識別子のうち先頭が名前空間区切り文字で始まるもので、 \Foo\Bar のようなものです。名前空間 \Foo も完全修飾名です。
名前解決は、これらの解決ルールによって行われます。
- 完全修飾された関数、クラス、定数へのコールはコンパイル時に解決されます。 たとえば、new \A\B は A\B クラスと解釈されます。
- 非修飾名および (完全修飾でない) 修飾名の変換は、現在のインポートルールに基づいてコンパイル時に行われます。 たとえば、名前空間 A\B\C が C という名前でインポートされている場合、 C\D\e() へのコールは A\B\C\D\e() と変換されます。
- 名前空間内で、インポートルールによる変換が行われなかった修飾名は 現在の名前空間が先頭に付加されます。たとえば、 C\D\e() へのコールが名前空間 A\B 内で行われた場合、それは A\B\C\D\e() に変換されます。
- 非修飾クラス名の変換は、現在のインポートルールに基づいてコンパイル時に行われます (インポートされた短い名前がフルネームに置き換わります)。たとえば、 名前空間 A\B\C が C という名前でインポートされている場合、 new C() は new A\B\C() と変換されます。
-
名前空間内 (ここでは A\B としましょう) で、非修飾な関数へのコールは実行時に解決されます。
関数 foo() のコールは、次のように解決されます。
- まず現在の名前空間から関数 A\B\foo() を探します。
- 次に グローバル 関数 foo() を探します。
-
名前空間内 (ここでは A\B としましょう) で、
非修飾あるいは (完全修飾でない) 修飾なクラスへのコールは実行時に解決されます。
new C() や new D\E()
がどのように解決されるかを示します。
new C() の場合は、
- まず現在の名前空間からクラス A\B\C を探します。
- A\B\C を autoload します。
- 現在の名前空間を先頭につけた A\B\D\E を探します。
- A\B\D\E を autoload します。
例1 名前解決の例
<?php
namespace A;
use B\D, C\E as F;
// 関数のコール
foo(); // まず名前空間 "A" で定義されている "foo" のコールを試み、
// 次にグローバル関数 "foo" をコールします
\foo(); // グローバルスコープで定義されている関数 "foo" をコールします
my\foo(); // 名前空間 "A\my" で定義されている関数 "foo" をコールします
F(); // まず名前空間 "A" で定義されている "F" のコールを試み、
// 次にグローバル関数 "F" をコールします
// クラスの参照
new B(); // 名前空間 "A" で定義されているクラス "B" のオブジェクトを作成します
// 見つからない場合は、クラス "A\B" の autoload を試みます
new D(); // インポートルールを使用し、名前空間 "B" で定義されているクラス "D" のオブジェクトを作成します
// 見つからない場合は、クラス "B\D" の autoload を試みます
new F(); // インポートルールを使用し、名前空間 "C" で定義されているクラス "E" のオブジェクトを作成します
// 見つからない場合は、クラス "C\E" の autoload を試みます
new \B(); // グローバルスコープで定義されているクラス "B" のオブジェクトを作成します
// 見つからない場合は、クラス "B" の autoload を試みます
new \D(); // グローバルスコープで定義されているクラス "D" のオブジェクトを作成します
// 見つからない場合は、クラス "D" の autoload を試みます
new \F(); // グローバルスコープで定義されているクラス "F" のオブジェクトを作成します
// 見つからない場合は、クラス "F" の autoload を試みます
// 別の名前空間から使用する静的メソッド/関数
B\foo(); // 名前空間 "A\B" の関数 "foo" をコールします
B::foo(); // 名前空間 "A" で定義されているクラス "B" のメソッド "foo" をコールします
// クラス "A\B" が見つからない場合はクラス "A\B" の autoload を試みます
D::foo(); // インポートルールを使用し、名前空間 "B" で定義されているクラス "D" のメソッド "foo" をコールします
// クラス "B\D" が見つからない場合はクラス "B\D" の autoload を試みます
\B\foo(); // 名前空間 "B" の関数 "foo" をコールします
\B::foo(); // グローバルスコープのクラス "B" のメソッド "foo" をコールします
// クラス "B" が見つからない場合はクラス "B" の autoload を試みます
// 現在の名前空間から使用する静的メソッド/関数
A\B::foo(); // 名前空間 "A\A" のクラス "B" のメソッド "foo" をコールします
// クラス "A\A\B" が見つからない場合はクラス "A\A\B" の autoload を試みます
\A\B::foo(); // 名前空間 "A" のクラス "B" のメソッド "foo" をコールします
// クラス "A\B" が見つからない場合はクラス "A\B" の autoload を試みます
?>