English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
PHP 名前空間(namespace)はPHP 5.3に含まれる、C#やJavaを学んだことがあるなら、名前空間は新しいものではないでしょう。しかし、PHPでは非常に重要な意味を持っています。
PHP 名前空間は以下の二つの問題を解決できます:
ユーザーが書いたコードとPHP内部のクラス/関数/定数またはサードパーティのクラス/関数/定数間の名前衝突
非常に長い識別子名(通常は第一種問題を緩和するために定義される)に対して、(短い)別名を設定することで、ソースコードの可読性を向上させます。
デフォルトでは、すべての定数、クラス、関数名はグローバル空間に配置されます。PHP が名前空間をサポートする前にと同様です。
名前空間はキーワード namespace で宣言されます。ファイル内に名前空間がある場合、他のすべてのコードよりも前に名前空間を宣言する必要があります。構文形式は以下の通りです;
<?php // 「MyProject」名前空間内のコードを定義しています ネームスペースMyProject; // ... コード ...
同じファイル内で異なる名前空間コードを定義することもできます。例えば:
<?php ネームスペースMyProject; const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } namespace AnotherProject; const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } ?>
単一のファイル内で複数の名前空間を定義するこの構文は推奨されません。以下の大括弧形式の構文を使用することをお勧めします。
<?php namespace MyProject { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } } namespace AnotherProject { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } } ?>
グローバルな名前空間外のコードと名前空間内のコードを組み合わせる場合、大括弧形式の構文を使用する必要があります。グローバルコードは、名前のない namespace ステートメントと大括弧で括られる必要があります。例えば:
<?php namespace MyProject { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } } namespace { // 全体的なコード session_start(); $a = MyProject\connect(); echo MyProject\Connection::start(); } ?>
名前空間を宣言する前に合法なコードは、ソースファイルのエンコーディング方法を定義する declare ステートメントのみです。名前空間の宣言前に、PHP でないコードや空白文字は一切出現してはなりません。
<?php declare(encoding='UTF')-8'); //複数の名前空間とその外のコードの定義 namespace MyProject { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ } } namespace { // 全体的なコード session_start(); $a = MyProject\connect(); echo MyProject\Connection::start(); } ?>
以下のコードは構文エラーが発生します:
<html> <?php ネームスペースMyProject; // 「<html>」が名前空間の前に現れると致命的なエラーが発生します - 名前空間はプログラムスクリプトの最初の文でなければなりません ?>
ディレクトリやファイルと同様に、PHP 名前空間も階層的な名前空間の指定を許可しています。したがって、名前空間の名前は階層的に定義できます:
<?php namespace MyProject\Sub\Level; //階層的な単一の名前空間を宣言します const CONNECT_OK = 1; class Connection { /* ... */ } function Connect() { /* ... */ } ?>
上記の例では、定数 MyProject\Sub\Level\CONNECT_OK、クラス MyProject\Sub\Level\Connection、および関数 MyProject\Sub\Level\Connect が作成されました。
PHP 名前空間内のクラス名は、以下の3つの方法で参照できます:
非限定名、または接頭辞を含まないクラス名例えば $a = new foo(); または foo::staticmethod();。現在の名前空間が currentnamespace である場合、foo は currentnamespace\foo として解釈されます。foo を使用するコードが全体的である場合、名前空間に含まれていないコードでは foo は foo として解釈されます。警告:名前空間内の関数や定数が未定義である場合、非限定の関数名や定数名は全体的な関数名や定数名として解釈されます。
限定名、または接頭辞を含む名前例えば $a = new subnamespace\foo(); または subnamespace\foo::staticmethod();。現在の名前空間が currentnamespace である場合、foo は currentnamespace\subnamespace\foo として解釈されます。foo を使用するコードが全体的である場合、名前空間に含まれていないコードでは foo は subnamespace\foo として解釈されます。
完全限定名、またはグローバルプレフィックス演算子を含む名前例えば、$a = new \currentnamespace\foo(); または \currentnamespace\foo::staticmethod();。この場合、fooは常にコード内の文字名(literal name)currentnamespace\fooとして解析されます。
以下はこれらの3つの方法を使用した例です:
file1.php ファイルコード
<?php namespace Foo\Bar\subnamespace; const FOO = 1; function foo() {} class foo { static function staticmethod() {} } ?>
file2.php ファイルコード
<?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 ?>
任意のグローバルクラス、関数、定数にアクセスする場合は、完全限定名を使用できます。例えば、\strlen()や\Exception、\INI_ALLなど。
ナームスペース内でグローバルクラス、関数、定数にアクセスする:
<?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をシリアライズ ?>
PHPの名前空間の実装はその言語の動的特徴に影響されています。したがって、以下のコードを名前空間に変換する場合、要素に動的にアクセスする必要があります。
example1.php ファイルコード:
<?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を出力 ?>
完全限定名(命名空間接頭辞を含むクラス名)を使用する必要があります。注意、動的なクラス名、関数名、または定数名の完全限定名と限定名は区別されませんので、先頭の反斜杠は必要ありません。
名前空間の要素に動的にアクセスする
<?php namespace namespacename; class classname { function __construct() { echo __METHOD__, '\n'; } } function funcname() { echo __FUNCTION__, '\n'; } const constname = 'namespaced'; include 'example1.php'; $a = 'classname'; $obj = new $a; // 出力 classname::__construct $b = 'funcname'; $b(); // 出力関数名 echo constant('constname'), '\n'; // 出力 global /* もしダブルクォートを使用する場合、'\\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を出力します constant('\namespacename\constname'), '\n';を出力します // ネームスペースを出力します constant('namespacename\constname'), '\n';を出力します // ネームスペースを出力します ?>
PHPは、現在のネームスペース内の要素にアクセスするための二つの抽象的な方法をサポートしています、__NAMESPACE__マジック定数とnamespaceキーワード。
定数__NAMESPACE__の値は、現在のネームスペース名を含む文字列です。グローバルな、どのネームスペースにも含まれないコードでは、空の文字列を含みます。
__NAMESPACE__の例、ネームスペース内のコード
<?php ネームスペースMyProject; '"', __NAMESPACE__, '"';'を出力します // "MyProject"を出力します ?>
__NAMESPACE__の例、グローバルコード
<?php '"', __NAMESPACE__, '"';'を出力します // ""を出力します ?>
定数__NAMESPACE__は、動的に名称を作成する際に非常に役立ちます、例えば:
__NAMESPACE__を動的に名称を作成するために使用します
<?php ネームスペースMyProject; function get($classname) { $a = __NAMESPACE__ . '\' . $classname; new$aを返します } ?>
キーワードnamespaceは、現在のネームスペースや子ネームスペースの要素を明示的にアクセスするために使用できます。これはクラス内のself演算子に等价です。
ネームスペース演算子、ネームスペース内のコード
<?php ネームスペースMyProject; blah\blahをmineとして使用します // 「ネームスペースの使用:インポート」を参照してください/""をアライアスします blah\mine(); // 関数blah\blah\mine()を呼び出します ネームスペース\blah\mine(); // 関数MyProject\blah\mine()を呼び出します namespace\func(); // 関数MyProject\func()を呼び出します namespace\sub\func(); // 関数MyProject\sub\func()を呼び出します namespace\cname::method(); // クラスMyProject\cnameの静的メソッド"method"を呼び出します $a = new namespace\sub\cname(); // クラスMyProject\sub\cnameのオブジェクトをインスタンス化します $b = namespace\CONSTANT; // 定数 MyProject\CONSTANT の値を $b に代入します ?>
ネームスペース演算子、グローバルコード
<?php namespace\func(); // 関数 func() を呼び出します namespace\sub\func(); // 関数 sub\func() を呼び出します namespace\cname::method(); // クラス cname の静的メソッド「method」を呼び出します $a = new namespace\sub\cname(); // クラス sub\cname のオブジェクトをインスタンス化します $b = namespace\CONSTANT; // 定数 CONSTANT の値を $b に代入します ?>
PHPのネームスペースは、クラス名に別名を付けたり、ネームスペース名に別名を付けたりする二種類の別名またはインポート方法をサポートしています。
PHPでは、別名は use 演算子を通じて実現されます。以下は、すべての可能性のある三种のインポート方法を使用した例です:
1、use演算子を用いたインポート/別名の使用
<?php ネームスペース foo; use My\Full\Classname as Another; // 以下の例は use My\Full\NSname as NSname と同じです use My\Full\NSname; // グローバルクラスをインポートする use \ArrayObject; $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 オブジェクトをサンプル化する ?>
2、一行に複数のuse文を含む
<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // サンプル化する My\Full\Classname オブジェクト NSname\subns\func(); // 関数 My\Full\NSname\subns\func を呼び出す ?>
インポート操作はコンパイル時に実行されるが、動的クラス名、関数名、または定数名はそうではありません。
3、インポートと動的名称
<?php use My\Full\Classname as Another, My\Full\NSname; $obj = new Another; // サンプル化する My\Full\Classname オブジェクト $a = 'Another'; $obj = new $a; // Another オブジェクトの実体化 ?>
また、インポート操作は非限定名と限定名にのみ影響を与えます。完全限定名は確定的であるため、インポートの影響を受けません。
4、インポートと完全限定名
<?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 クラスの例示 ?>
命名空間内で、PHP が非限定のクラス、関数、または定数の名前に出会った場合、異なる優先戦略を使用してその名前を解釈します。クラス名は常に現在の命名空間の名前に解釈されます。したがって、システム内部や命名空間に含まれていないクラス名にアクセスする場合、完全限定名を使用する必要があります。例えば:
1、命名空間内でグローバルクラスにアクセス
<?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; // 致命的なエラー、A\B\C\ArrayObject クラスが見つかりません ?>
関数や定数に対して、現在の命名空間にその関数や定数が存在しない場合、PHP はグローバル空間の関数や定数を使用する。
2、命名空間内の代替的なグローバル関数/定数
<?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"; } ?>
名前空間が未定義の場合、すべてのクラスと関数の定義はグローバル空間内にあります。PHPが名前空間概念を導入する前と同じです。名前の前に\を付けることで、その名前がグローバル空間の名前であることを示します。たとえその名前が他の名前空間内に存在する場合でもです。
グローバル空間の指定
<?php namespace A\B\C; /* この関数はA\B\C\fopenです */ function fopen() { /* ... */ $f = \fopen(...); // グローバルのfopen関数を呼び出します return $f; } ?>
名前空間が導入された後、最も間違えやすいのはクラスの使用ですが、そのクラスの探索パスはどのようなものですか。
<?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」をロードしようとします new D(); // インポートルールを使用して、名前空間「B」で定義されたクラス「D」のオブジェクトを生成します // 見つからなかった場合、自動的にクラス「B\D」をロードしようとします new F(); // インポートルールを使用して、名前空間「C」で定義されたクラス「E」のオブジェクトを生成します // クラス「C\E」が見つからなかった場合、自動的にクラス「C\E」をロードしようとします new \B(); // グローバル空間で定義されたクラス「B」のオブジェクトを生成します // 見つからなかった場合、自動的にクラス「B」をロードしようとします new \D(); // グローバル空間で定義されたクラス「D」のオブジェクトを生成します // 見つからなかった場合、自動的にクラス「D」をロードしようとします new \F(); // グローバル空間で定義されたクラス「F」のオブジェクトを生成します // 見つからなかった場合、自動的にクラス「F」をロードしようとします // 別の名前空間内の静的メソッドまたは名前空間関数を呼び出します B\foo(); // 名前空間「A\B」内の関数「foo」を呼び出します B::foo(); // 名前空間「A」で定義されたクラス「B」の「foo」メソッドを呼び出します // クラス「A\B」が見つからなかった場合、自動的にクラス「A\B」をロードしようとします D::foo(); // インポートルールを使用して、名前空間「B」で定義されたクラス「D」の「foo」メソッドを呼び出します // クラス「B\D」が見つからない場合、自動的にクラス「B\D」をロードしようと試みます \B\foo(); // 名前空間「B」の関数「foo」を呼び出します \B::foo(); // グローバル空間内のクラス「B」の「foo」メソッドを呼び出します // クラス「B」が見つからない場合、自動的にクラス「B」をロードしようと試みます // 現在の名前空間内の静的メソッドや関数 A\B::foo(); // 名前空間「A\A」で定義されたクラス「B」の「foo」メソッドを呼び出します // クラス「A\A\B」が見つからない場合、自動的にクラス「A\A\B」をロードしようと試みます \A\B::foo(); // 名前空間「A」で定義されたクラス「B」の「foo」メソッドを呼び出します // クラス「A\B」が見つからない場合、自動的にクラス「A\B」をロードしようと試みます ?>
名前解釈は以下の規則に従います:
完全限定名前の関数、クラス、定数の呼び出しはコンパイル時に解析されます。例えば new \A\B がクラスとして解析されます A\B。
すべての非限定名前と限定名前(完全限定名でない)は、現在のインポート規則に従ってコンパイル時に変換されます。例えば、名前空間 A\B\C がインポートされます C、それで C\D\e() の呼び出しは以下に変換されます A\B\C\D\e()。
名前空間内部で、現在のインポート規則に従わないすべての限定名前は、その前に現在の名前空間名が加わります。例えば、名前空間 A\B 内部呼び出し C\D\e()、そのため、 C\D\e() は以下に変換されます A\B\C\D\e() 。
非限定クラス名は、現在のインポート規則に従ってコンパイル時に変換されます(短いインポート名を完全名で置き換えます)。例えば、名前空間 A\B\C インポートとしてCが指定された場合、 new C() は以下に変換されます new A\B\C() 。
名前空間内部(例えばA\B)で非限定名前の関数呼び出しは、実行時に解析されます。例えば、関数 foo() の呼び出しは以下のように解析されます:
現在の名前空間内で名前が A\B\foo() の関数
検索し、呼び出すことを試みます グローバル(global) 空間内の関数 foo()。
名前空間(例えばA\B)内部で非限定名前や限定名前のクラス(完全限定名でない)の呼び出しは、実行時に解析されます。以下はその呼び出しです new C() 及び new D\E() の解釈プロセス: new C()の解釈: new D\E()の解釈: 全局名前空間内のグローバルクラスを参照するには、完全限定名を使用する必要があります new \C()。
クラス名の前に現在の名前空間名を加えて、以下のようになります:A\B\D\E、そのクラスを検索します。
自動的にクラスをロードしようと試みます A\B\D\E。
現在の名前空間内で検索A\B\Cクラス。
自動的にクラスをロードしようと試みますA\B\C。