PHP ネームスペース (namespace) は PHP 5.3 で追加されました。C# と Java を学習したことがある方にとって、ネームスペースは新しいものではありません。 ただし、PHP では依然として非常に重要な意味を持っています。
PHP 名前空間は、次の 2 種類の問題を解決できます。
ユーザーが作成したコードと、PHP の内部クラス/関数/定数またはサードパーティのクラス/関数/定数の間で名前が競合します。
ソース コードの読みやすさを向上させるために、非常に長い識別子名 (通常、最初の種類の問題を軽減するために定義される) のエイリアス (または短い) 名を作成します。
デフォルトでは、PHP が名前空間をサポートする前と同様に、すべての定数、クラス、関数名はグローバル空間に配置されます。
名前空間はキーワード namespace を使用して宣言されます。ファイルに名前空間が含まれている場合は、他のすべてのコードの前に名前空間を宣言する必要があります。構文形式は次のとおりです。
<?php // 「MyProject」名前空間にコードを定義します。 namespace MyProject; // ... code...
同じファイル内で次のような異なる名前空間コードを定義することもできます。
<?php namespace MyProject;const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */ }namespace AnotherProject;const CONNECT_OK = 1;class Connection { /* .. . */ }関数 connect() { /* ... */ }?>
この構文を使用して 1 つのファイルに複数の名前空間を定義することはお勧めできません。次の中括弧形式の構文を使用することをお勧めします。
<?phpnamespace MyProject { const CONNECT_OK = 1; class Connection { /* ... */ } function connect() { /* ... */ }}namespace AnotherProject { const CONNECT_OK = 1; class Connection { /* .. . */ } 関数 connect() { /* ... */ }}?>
グローバル非名前空間コードと名前空間コードを組み合わせるには、中括弧構文のみを使用できます。グローバル コードは、次のように中括弧が続く名前のない名前空間ステートメントで囲む必要があります。
<?phpnamespace MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */ }}namespace { // グローバル コード session_start();$a = MyProject connect();echo MyProjectConnection::start();}?>
名前空間を宣言する前の唯一の有効なコードは、ソース ファイルのエンコーディングを定義する宣言ステートメントです。空白を含むすべての非 PHP コードは、名前空間宣言の前に置くことはできません。
<?phpdeclare(encoding='UTF-8'); //名前空間 MyProject に含まれない複数の名前空間とコード名前空間を定義する {const CONNECT_OK = 1;class Connection { /* ... */ }function connect () { / * ... */ }}namespace { // グローバル コード session_start();$a = MyProjectconnect();echo MyProjectConnection::start();}?>
次のコードは構文エラーを引き起こします。
<html><?phpnamespace MyProject; // 名前空間の前に「<html>」が現れると致命的なエラーが発生します - 名前空間はプログラム スクリプトの最初のステートメントでなければなりません?>
ディレクトリとファイルの関係と同様に、PHP 名前空間でも階層的な名前空間名を指定できます。したがって、名前空間名は階層的に定義できます。
<?phpnamespace MyProjectSubLevel; //階層的な単一の名前空間を宣言します const CONNECT_OK = 1;class Connection { /* ... */ }function Connect() { /* ... */ }?>
上記の例では、定数 MyProjectSubLevelCONNECT_OK、クラス MyProjectSubLevelConnection、および関数 MyProjectSubLevelConnect を作成します。
PHP 名前空間のクラス名は、次の 3 つの方法で参照できます。
非修飾名、または $a=new foo() や foo::staticmethod(); などの接頭辞のないクラス名。現在の名前空間が currentnamespace の場合、foo は currentnamespacefoo に解決されます。 foo を使用するコードがグローバルであり、どの名前空間にもコードが含まれていない場合、foo は foo として解決されます。 警告: ネームスペース内の関数または定数が未定義の場合、修飾されていない関数または定数名はグローバル関数または定数名に解決されます。
修飾名、または $a = new subnamespacefoo(); や subnamespacefoo::staticmethod(); などのプレフィックスを含む名前。現在の名前空間が currentnamespace の場合、foo は currentnamespacesubnamespacefoo に解決されます。 foo を使用するコードがグローバルであり、コードがどの名前空間にも含まれていない場合、foo は subnamespacefoo に解決されます。
完全修飾名、またはグローバル接頭辞演算子を含む名前($a = new currentnamespacefoo(); または currentnamespacefoo::staticmethod(); など。この場合、foo はコード内で常にリテラル名 currentnamespacefoo に解決されます。
これら 3 つの方法の使用例を次に示します。
file1.php ファイルコード
<?phpnamespace FooBarsubnamespace; const FOO = 1;function foo() {}class foo{ static function staticmethod() {}}?>
file2.php ファイルコード
<?phpnamespace FooBar;include 'file1.php';const FOO = 2;function foo() {}class foo{ static function staticmethod() {}}/* 修飾されていない名前*/foo(); // 解析しますは関数 FooBarfoofoo::staticmethod(); // これはクラス FooBarfoo に解析され、メソッドは staticmethodecho FOO です。定数 FooBarFOO/* 修飾名 */subnamespacefoo() に解決します。 // 関数 FooBarsubnamespacefoosubnamespacefoo::staticmethod() に解決します。 // クラス FooBarsubnamespace に解決します。 foo, // およびクラス メソッド staticmethodecho subnamespaceFOO // 定数 FooBarsubnamespaceFOO /* に解析されます。完全修飾名 */FooBarfoo(); // 関数 FooBarfooFooBarfoo::staticmethod(); // クラス FooBarfoo に解決します。メソッド staticmethodecho FooBarFOO; //定数 FooBarFOO?> として解決されます。
グローバル クラス、関数、または定数にアクセスするには、strlen()、Exception、INI_ALL などの完全修飾名を使用できることに注意してください。
ネームスペース内のグローバル クラス、関数、定数にアクセスします。
<?phpnamespace 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 ファイルのコード:
<?phpclass classname{ function __construct() { echo __METHOD__,"n"; }function funcname(){ echo __FUNCTION__,"n";}const constname = "global";$a = 'classname';$obj = new $a; // classname::__construct$b = 'funcname';$b(); // funcnameecho を出力します。 constant('constname'), "n"; // グローバルを出力します?>
完全修飾名 (名前空間プレフィックスを含むクラス名) を使用する必要があります。動的クラス名、関数名、または定数名では修飾名と完全修飾名に違いがないため、先頭のバックスラッシュは不要であることに注意してください。
名前空間の要素に動的にアクセスする
<?phpnamespace namespacename;class classname{ function __construct() { echo __METHOD__,"n"; }function funcname(){ echo __FUNCTION__,"n";}const constname = "namespaced";include 'example1.php' ;$a = 'クラス名';$obj = new $a // 出力クラス名::__construct$b = 'funcname';$b(); // 出力関数名 echo constant('constname'), "n"; // 出力 global/* 二重引用符が使用されている場合、使用方法は "\namespacename\classname" です。 "* /$a = '名前空間名クラス名';$obj = new $a; // 出力名前空間名クラス名::__construct$a = '名前空間名クラス名';$obj = new $a; //出力 namespacenameclassname::__construct$b = 'namespacenamefuncname';$b(); // 出力 namespacenamefuncname$b = 'namespacenamefuncname';$b(); // 出力 namespacenamefuncnameecho constant( 'namespacenameconstname'), "n"; // 出力 namespacedecho constant('namespacenameconstname'), "n";名前空間を出力しますか?>
PHP は、現在の名前空間内の要素にアクセスする 2 つの抽象メソッド、__NAMESPACE__ マジック定数と名前空間キーワードをサポートしています。
定数 __NAMESPACE__ の値は、現在の名前空間の名前を含む文字列です。どの名前空間にも含まれていないグローバル コードには、空の文字列が含まれます。
__NAMESPACE__ の例、名前空間内のコード
<?phpnamespace MyProject;echo '"', __NAMESPACE__, '"' // "MyProject" を出力します?>
__NAMESPACE__ の例、グローバル コード
<?phpecho '"', __NAMESPACE__, '"' // 出力 ""?>
定数 __NAMESPACE__ は、名前を動的に作成する場合に役立ちます。次に例を示します。
__NAMESPACE__ を使用して名前を動的に作成する
<?phpnamespace MyProject;function get($classname){ $a = __NAMESPACE__ . $classname; }?>
キーワード名前空間を使用すると、現在の名前空間またはサブ名前空間内の要素に明示的にアクセスできます。これは、クラスの self 演算子に相当します。
名前空間演算子、名前空間内のコード
<?phpnamespace MyProject;use blahblah asmine; // 「名前空間の使用: import/aliasing」を参照してください。 blahmine(); // 関数 blahblahmine()namespaceblahmine();関数 MyProjectblahmine()namespacefunc() を呼び出します。 // 関数 MyProjectfunc()namespacesubfunc() を呼び出します。 MyProjectsubfunc()namespacecname::method(); // クラス MyProjectcname$a = new namespacesubcname() の静的メソッド "method" を呼び出します // クラス MyProjectsub のオブジェクトをインスタンス化します。 cname$b = namespaceCONSTANT; // 定数 MyProjectCONSTANT の値を $b?>
名前空間演算子、グローバル コード
<?phpnamespacefunc(); // 関数 func()namespacesubfunc() を呼び出します。 // 関数 subfunc()namespacecname::method() を呼び出します。 // 静的メソッド "method" を呼び出します。 class cname$a = new namespacesubcname(); // クラスのオブジェクトをインスタンス化 subcname$b = namespaceCONSTANT; // 定数 CONSTANT の値を $b?>
PHP 名前空間サポートでは、エイリアスまたはインポートを使用する 2 つの方法があります。クラス名にエイリアスを使用する方法と、名前空間名にエイリアスを使用する方法です。
PHP では、エイリアスは use 演算子を介して実装されます。次に、3 つの可能なインポート メソッドをすべて使用した例を示します。
1. use 演算子を使用してエイリアスをインポート/使用します
<?phpnamespace foo;use MyFullClassname as Another;// 次の例は use MyFullNSname as NSname use MyFullNSname;// グローバル クラスをインポート use ArrayObject;$obj = new namespaceAnother; // fooAnother オブジェクトをインスタンス化します $obj = new Another; // MyFullClassname オブジェクトをインスタンス化します NSnamesubnsfunc();関数を呼び出します MyFullNSnamesubnsfunc$a = new ArrayObject(array(1)); // ArrayObject オブジェクトをインスタンス化します // "use ArrayObject" を使用しない場合は、fooArrayObject オブジェクトをインスタンス化しますか? >
2. 1 行に複数の use ステートメントが含まれる
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // MyFullClassname オブジェクトをインスタンス化します NSnamesubnsfunc() // 関数 MyFullNSname を呼び出します。サブネット機能?>
インポート操作はコンパイル中に実行されますが、動的クラス名、関数名、または定数名は実行されません。
3. インポート名と動的名
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // MyFullClassname オブジェクトをインスタンス化します $a = 'Another';$obj = new $a; //別のオブジェクト?>
さらに、インポート操作は、非修飾名と修飾名のみに影響します。完全修飾名は決定的であるため、インポートの影響を受けません。
4. インポート名と完全修飾名
<?phpuse MyFullClassname as Another, MyFullNSname;$obj = new Another; // MyFullClassname をインスタンス化します。 class $obj = new Another; // 別のクラスをインスタンス化します $obj = new Another thing; // MyFullClassnamething クラスをインスタンス化します $obj = new Anotherthing // Anotherthing クラスをインスタンス化しますか?>
名前空間内で、PHP が修飾されていないクラス、関数、または定数名を検出すると、別の優先順位戦略を使用して名前を解決します。クラス名は常に現在の名前空間内の名前に解決されます。したがって、システムの内部にあるクラス名、または名前空間に含まれていないクラス名にアクセスする場合は、次のように完全修飾名を使用する必要があります。
1. 名前空間内のグローバル クラスにアクセスする
<?phpnamespace ABC;class Exception extends Exception {}$a = new Exception('hi'); // $a はクラス ABCException のオブジェクト $b = new Exception( 'hi'); // $b はクラスのオブジェクトです Exception $c = new ArrayObject; // 致命的なエラー、クラス ABCArrayObject が見つかりません?>
関数と定数の場合、関数または定数が現在の名前空間に存在しない場合、PHP はグローバル空間で関数または定数を使用するようにフォールバックします。
2. 名前空間内のグローバル関数/定数をバックアップする
<?phpnamespace ABC;const E_ERROR = 45;function strlen($str){ return strlen($str) - 1;}echo E_ERROR, "n" // 出力 "45"echo INI_ALL, " n"; // 出力 "7" - グローバル定数 INI_ALLecho strlen('hi'), "n"; // 出力 "2"if (is_array('hi')) { // 出力 "配列ではありません" echo "配列ではありませんn";} else { echo "配列ではありませんn";}?>
名前空間が定義されていない場合、PHP に名前空間の概念が導入される前と同様に、すべてのクラスと関数はグローバル空間で定義されます。名前の前に を付けると、名前が別の名前空間にある場合でも、その名前がグローバル空間にあることを示します。
グローバル空間命令を使用する
<?phpnamespace ABC;/* この関数は ABCfopen */function fopen() { /* ... */ $f = fopen(...); // グローバルを呼び出します。 fopen 関数は $f;} を返します ?>
名前空間の導入以来、最もエラーが発生しやすいのは、クラスを使用するとき、このクラスの検索パスは何かということです。
<?phpnamespace A;use BD, CE as F;// 関数呼び出し foo(); // まず、名前空間 "A" で定義された関数 foo() を呼び出してみます。 // 次に、グローバル関数を呼び出してみます。 function" foo"foo(); // グローバル空間関数 "foo" を呼び出します。 myfoo(); // 名前空間 "Amy" で定義された関数 "foo" を呼び出します。最初に名前空間 "A" で定義された関数 "F" を呼び出してみます // 次に、グローバル関数 "F" を呼び出してみます // クラス参照 new B() // 名前空間 "A" で定義されたクラス "B" を作成しますclass "AB" new D(); // 見つからない場合は、クラス "AB" new D(); // インポート ルールを使用して、名前空間 "B" に定義されたクラス "D" のオブジェクトを作成します。 " // 見つからない場合は、クラス "BD" new を自動的にロードしようとします。 F(); // インポート ルールを使用して、名前空間 "C" に定義されたクラス "E" のオブジェクトを作成します // 見つからない場合は、クラス "CE" の自動ロードを試みます new B(); // オブジェクトを作成しますグローバル空間で定義されたクラス "B" の // 見つからない場合は、クラス "B" の自動ロードを試みます new D(); // グローバル空間で定義されたクラス "D" のオブジェクトを作成します // 見つからない場合は、自動ロードクラス「D」新規F(); // グローバル空間で定義されたクラス "F" のオブジェクトを作成します // 見つからない場合は、クラス "F" の自動ロードを試みます // 別の名前空間の静的メソッドまたは名前空間関数を呼び出します Bfoo() ; // 名前空間 "AB" の関数 "foo" を呼び出す B::foo(); // 名前空間 "A" で定義されたクラス "B" のメソッド "foo" を呼び出す // クラス "AB" の場合見つかりません次に、クラス "AB" を自動的にロードしてみます。 D::foo(); // インポート ルールを使用して、名前空間 "B" で定義されたクラス "D" の "foo" メソッドを呼び出します。 // クラス "BD" の場合" " 見つからない場合は、クラス "BD"Bfoo() // 名前空間 "B" で関数 "foo" を呼び出します。 B::foo(); //大域空間クラス「B」の関数"foo" メソッド // クラス "B" が見つからない場合は、クラス "B" の自動ロードを試みます // 現在の名前空間の静的メソッドまたは関数 AB::foo() // 名前空間 "A" を呼び出します。 A" で定義されたクラス "B" の "foo" メソッド // クラス "AAB" が見つからない場合は、クラス "AAB"AB::foo() の自動ロードを試みます。 //名前空間「A」で定義されたクラス「B」の「foo」メソッドを呼び出します // クラス「AB」が見つからない場合は、クラス「AB」の自動ロードを試みますか?>
名前解決は次のルールに従います。
関数、クラス、定数の完全修飾名への呼び出しはコンパイル時に解決されます。たとえば、 new AB はクラスABに解決されます。
すべての非修飾名と修飾名 (完全修飾名ではない) は、現在のインポート ルールに従ってコンパイル時に変換されます。たとえば、名前空間ABCがCとしてインポートされた場合、 CDe()の呼び出しはABCDe()に変換されます。
ネームスペース内では、インポート ルールに従って変換されないすべての修飾名には、現在のネームスペース名が先頭に付加されます。たとえば、 CDe() が名前空間AB内で呼び出された場合、 CDe() はABCDe()に変換されます。
修飾されていないクラス名は、現在のインポート ルールに従ってコンパイル時に変換されます (短いインポート名の代わりに完全名が使用されます)。たとえば、名前空間ABCが C としてインポートされる場合、 new C()はnew ABC()に変換されます。
名前空間 (例: AB) 内では、修飾されていない名前への関数呼び出しは実行時に解決されます。たとえば、関数foo()の呼び出しは次のように解析されます。
現在の名前空間でABfoo()という名前の関数を見つけます。
グローバル空間で関数foo() を見つけて呼び出してみます。
名前空間 (例: AB ) 内の非修飾名または修飾名クラス (非完全修飾名) への呼び出しは実行時に解決されます。以下は、 new C()およびnew DE()を呼び出す解析プロセスです。 new C()の解析:
現在の名前空間でクラスABCを検索します。
クラスABC を自動ロードしてみます。
新しい DE()の分析:クラス名の前に現在の名前空間名を付加してABDEとなり、そのクラスを探します。
クラスABDE を自動ロードしてみます。
グローバル名前空間内のグローバル クラスを参照するには、完全修飾名new C()を使用する必要があります。