PHP ネームスペース (namespace) は PHP 5.3 で追加されました。C# と Java を学習したことがある方にとって、ネームスペースは新しいものではありません。 ただし、PHP では依然として非常に重要な意味を持っています。
PHP 名前空間は、次の 2 種類の問題を解決できます:
ユーザー作成コードと PHP 内部クラス/関数/定数またはサードパーティのクラス/関数/定数の間の名前の競合。
非常に長い識別子名 (通常、最初の種類の問題を軽減するために定義される) のエイリアス (または短い) 名を作成し、ソース コードの可読性を向上させます。
名前空間を定義する
デフォルトでは、PHP が名前空間をサポートする前と同様に、すべての定数、クラス、関数名はグローバル空間に配置されます。
名前空間では、通常、会社、企業、または個人の名前または略称を識別子として使用します。最初の文字は大文字にする必要があり、数字で始めることはできません。
名前空間はキーワード namespace を通じて宣言されます。ファイルに名前空間が含まれている場合は、他のすべてのコードの前に名前空間を宣言する必要があります。構文形式は次のとおりです。
<?php
// 'MyProject' 名前空間でコードを定義します
namespace MyProject;
// ... code...
?>
<?php
namespace MyProject1;
// MyProject1 名前空間の PHP コード
namespace MyProject2;
// MyProject2 名前空間の PHP コード
// 別の構文
namespace MyProject3 {
// MyProject3 名前空間の PHP コード
}
?>
名前空間を宣言する前の唯一の正当なコードは、ソース ファイルのエンコード宣言ステートメントを定義することです。空白を含むすべての非 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(); } ?>
次のコードには構文エラーが発生します:
<?php
namespace MyProject; // "" が名前空間の前に表示されます。プログラム スクリプトに属している必要があります 最初のステートメント
?>
subnamespace
サブネームスペースの宣言は、前の例とまったく同じです。唯一の違いは、名前空間とサブ名前空間を区切るためのシンボルを追加することです。
<?php
namespace 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 はサブ名前空間 foo に解決されます。 完全修飾名、またはグローバル接頭辞演算子を含む名前 ($a = new currentnamespacefoo(); または currentnamespacefoo::staticmethod(); など)。 この場合、foo はコード内で常にリテラル名 currentnamespacefoo に解決されます。 以下はこれら 3 つのメソッドの使用例です: file1.php ファイル コード file2.php ファイル コード グローバル クラス、関数、または定数にアクセスするには、完全修飾名を使用できることに注意してください。 strlen()、例外、INI_ALL など。 名前空間内のグローバル クラス、関数、定数にアクセスする: 名前空間と動的言語機能 PHP の名前空間の実装は、言語自体の動的機能の影響を受けます。したがって、以下のコードを名前空間に変換する場合は、要素に動的にアクセスします。 example1.php ファイルコード: 完全修飾名 (名前空間プレフィックスを含むクラス名) を使用する必要があります。動的クラス名、関数名、または定数名では修飾名と完全修飾名に違いがないため、先頭のバックスラッシュは不要であることに注意してください。 名前空間の要素への動的アクセス 名前空間キーワードと__NAMESPACE__定数 PHPは、現在の名前空間内の要素にアクセスする2つの抽象メソッド、__NAMESPACE__マジック定数と名前空間キーワードをサポートしています。 定数 __NAMESPACE__ の値は、現在の名前空間の名前を含む文字列です。どの名前空間にも含まれていないグローバル コードには、空の文字列が含まれます。 __NAMESPACE__ の例、名前空間のコード <?php __NAMESPACE__ の例, グローバル コード <?php 定数 __NAMESPACE__ は、名前を動的に作成する場合に便利です。 __NAMESPACE__ を使用して名前を動的に作成します <?php<?php
namespace Foo\Bar\subnamespace;
const FOO = 1;
function foo() {}
class foo
{
static function staticmethod() {}
}
?>
<?php
namespace Foo\Bar;
include 'file1.php';
const FOO = 2;
function foo() {}
class foo
{
static function staticmethod() {}
}
/* 非限定名称 */
foo(); // 解析为 Foo\Bar\foo resolves to function Foo\Bar\foo
foo::staticmethod();
// 解析为类 Foo\Bar\foo的静态方法staticmethod。resolves to class Foo\Bar\foo, method staticmethod
echo FOO; // resolves to constant 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
?>
<?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
class classname
{
function __construct()
{
echo __METHOD__,"\n";
}
}
function funcname()
{
echo __FUNCTION__,"\n";
}
const constname = "global";
$a = 'classname';
$obj = new $a; // prints classname::__construct
$b = 'funcname';
$b(); // prints funcname
echo constant('constname'), "\n"; // prints 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; // prints classname::__construct
$b = 'funcname';
$b(); // prints funcname
echo constant('constname'), "\n"; // prints global
/* note that if using double quotes, " \namespacename\classname" must be used */
$a = '\namespacename\classname';
$obj = new $a; // prints namespacename\classname::__construct
$a = 'namespacename\classname';
$obj = new $a; // also prints namespacename\classname::__construct
$b = 'namespacename\funcname';
$b(); // prints namespacename\funcname
$b = '\namespacename\funcname';
$b(); // also prints namespacename\funcname
echo constant('\namespacename\constname'), "\n"; // prints namespaced
echo constant('namespacename\constname'), "\n"; // also prints namespaced
?>
namespace MyProject;
echo '"', __NAMESPACE__, '"' // 出力 "MyProject"
?>
echo '"', __NAMESPACE__, '"'; // 出力 ""
?>
namespace MyProject;
function get($classname)
$a = __NAMESPACE__ . $classname;
?>
キーワード名前空間現在の名前空間またはサブ名前空間内の要素に明示的にアクセスするために使用できます。これは、クラスの self 演算子に相当します。 <?php
namespace MyProject;
use blah\blah as mine; // see "Using namespaces: importing/aliasing"
blah\mine(); // calls function blah\blah\mine()
namespace\blah\mine(); // calls function MyProject\blah\mine()
namespace\func(); // calls function MyProject\func()
namespace\sub\func(); // calls function MyProject\sub\func()
namespace\cname::method(); // calls static method "method" of class MyProject\cname
$a = new namespace\sub\cname(); // instantiates object of class MyProject\sub\cname
$b = namespace\CONSTANT; // assigns value of constant MyProject\CONSTANT to $b
?>
<?php namespace\func(); // calls function func() namespace\sub\func(); // calls function sub\func() namespace\cname::method(); // calls static method "method" of class cname $a = new namespace\sub\cname(); // instantiates object of class sub\cname $b = namespace\CONSTANT; // assigns value of constant CONSTANT to $b ?>
名前空間の使用: alias/import
PHP 名前空間は、エイリアスまたはインポートの 2 つの使用方法をサポートしています: クラス名として使用する エイリアスを使用する、またはエイリアスを使用する名前空間名用。 PHP は関数や定数のインポートをサポートしていないことに注意してください。
PHP では、エイリアスは use 演算子を使用して実装されます。 以下に、3 つのインポート方法をすべて使用する例を示します。 1. use 演算子を使用してエイリアスをインポート/使用します<?php namespace 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; // instantiates object of class Another $obj = new Another\thing; // 实例化对象的类 My\Full\Classname\thing $obj = new \Another\thing; // instantiates object of class Another\thing ?>
use キーワードの使用:
は PHP ファイルの先頭、つまり PHP 開始タグ <?php または名前空間宣言の後に use キーワードが続く必要があります。コードをインポートします。
use キーワードを使用してコードをインポートする場合、PHP はインポートされた名前空間が完全修飾されていると想定するため、クラス名の先頭に記号を追加する必要はありません。
use キーワードはグローバル スコープで使用する必要があります (つまり、クラスまたは関数では使用できません)
use キーワードを名前空間の宣言の下に配置して、他の名前空間にコードをインポートできます。
名前空間の使用: フォールバックグローバル関数/定数名前空間では、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 が名前空間の概念を導入する前と同様に、すべてのクラスと関数がグローバル空間で定義されます。名前に接頭辞を付けると、その名前が別の名前空間にある場合でも、その名前がグローバル空間にあることを示します。
グローバル空間の使用手順
グローバル名前空間を使用するには、クラス名の前にシンボルを追加するだけです。たとえば、 throw new Exception();
<?php namespace A\B\C; /* 这个函数是 A\B\C\fopen */ function fopen() { /* ... */ $f = \fopen(...); // 调用全局的fopen函数 return $f; ?>
名前空間の順序です。
名前空間の導入以来、最もエラーが発生しやすいのは、クラスを使用するとき、このクラスの検索パスは何でしょうか?
<?php
namespace A;
use BD, CE as F;
// 関数呼び出し
foo() // まず、名前空間 "A" で定義された関数 foo() を呼び出してみます。 // グローバル関数 "foo" をもう一度呼び出してみます
foo(); // グローバル空間関数 "foo" を呼び出します
myfoo(); // 名前空間 "Amy" で定義された関数 "foo" を呼び出します
F( ); // まず、名前空間 "A" で定義された関数 "F" を呼び出してみます
// 次に、グローバル関数 "F" を呼び出してみます
// クラス参照
new B(); // 名前空間を作成します。「A」で定義されたクラス「B」のオブジェクトです
// 見つからない場合は、クラス「AB」を自動的にロードしてみます
new D(); // インポート ルールを使用して、「A」で定義されたオブジェクトを作成します名前空間 "B" クラス "D" のオブジェクト
// 見つからない場合は、クラス "BD" の自動ロードを試みます
new F(); // インポート ルールを使用して、名前空間 " で定義されたクラス "E" のオブジェクトを作成します。 C" Object
// 見つからない場合は、クラス "CE" の自動ロードを試みます
new B(); // グローバル空間で定義されたクラス "B" のオブジェクトを作成します
// 見つからない場合は、自動的にロードを試みますload Class "B"
new D(); // グローバル空間に定義されたクラス "D" のオブジェクトを作成します
// 見つからない場合は、クラス "D" を自動的にロードしようとします
new F(); / / グローバル空間で定義されたクラス "F" のオブジェクトを作成します
// 見つからない場合は、クラス "F" を自動的にロードしようとします
// 別の名前空間の静的メソッドまたは名前空間関数を呼び出します
Bfoo () / / 名前空間「AB」の関数「foo」を呼び出す
B::foo(); // 名前空間「A」で定義されたクラス「B」の「foo」メソッドを呼び出す
// If not If class "AB" が見つかった場合は、クラス "AB" を自動的にロードしてみます
D::foo(); // インポート ルールを使用して、名前空間 "B" で定義されたクラス "D" の "foo" メソッドを呼び出します
//クラス「BD」が見つかりません。クラス「BD」を自動的にロードしてみます
Bfoo(); // 名前空間「B」の関数「foo」を呼び出します
B::foo(); //
のクラス "B" のグローバル空間 "foo" メソッド// クラス "B" が見つからない場合は、クラス "B" を自動的にロードしようとします
// 現在の名前空間の静的メソッドまたは関数
AB:: foo( ); // 名前空間「AA」で定義されたクラス「B」の「foo」メソッドを呼び出します
// クラス「AAB」が見つからない場合は、クラス「AAB」を自動的にロードしようとします
AB::foo(); // 名前空間「AB」で定義されたクラス「B」の「foo」メソッドを呼び出します
// クラス「AB」が見つからない場合は、クラス「AB」を自動的にロードしようとします
?> ;
名前解決は次の規則に従います:
1. 完全修飾名を持つ関数、クラス、および定数の呼び出しはコンパイル時に解決されます。たとえば、新しい AB はクラス AB に解決されます。
2. すべての非修飾名と修飾名 (非完全修飾名) は、現在のインポート ルールに従ってコンパイル時に変換されます。たとえば、名前空間 ABC が C としてインポートされた場合、CDe() の呼び出しは ABCDe() に変換されます。
3. 名前空間内では、インポート ルールに従って変換されないすべての修飾名の前に現在の名前空間名が付きます。たとえば、CDe() が名前空間 AB 内で呼び出された場合、CDe() は ABCDe() に変換されます。
4. 修飾されていないクラス名は、現在のインポート ルールに従ってコンパイル時に変換されます (短いインポート名の代わりに完全な名前が使用されます)。たとえば、名前空間 ABC が C としてインポートされる場合、 new C() は new ABC() に変換されます。
5. 名前空間 (例: AB) 内では、非修飾名への関数呼び出しは実行時に解決されます。たとえば、関数 foo() への呼び出しは次のように解析されます。
現在の名前空間で ABfoo() という名前の関数を見つけます
グローバル空間で関数 foo() を見つけて呼び出してみます。
6. 名前空間 (AB など) 内の非修飾名または修飾名クラス (非完全修飾名) への呼び出しは実行時に解決されます。以下は、new C() および new DE() を呼び出す解析プロセスです。 new C() の解析: new DE() の解析: グローバル名前空間内のグローバル クラスを参照するには、完全修飾名 new C() を使用する必要があります。
クラス名の前に現在の名前空間名を追加して「ABDE」となり、クラスを検索します。
クラス ABDE の自動ロードを試してください。
現在の名前空間でクラス ABC を検索します。
クラス ABC の自動ロードを試してください。