PHP名前空間(ネームスペース)
PHP名前空間(ネームスペース)はPHP 5.3で追加されました
ネームスペースとは何ですか?大まかに言えば、名前空間は物事をカプセル化する方法です。この抽象的な概念はさまざまな場所で見られます。たとえば、オペレーティング システムでは、ディレクトリは関連ファイルをグループ化するために使用され、ディレクトリ内のファイルの場合、名前空間の役割を果たします。たとえば、ファイル foo.txt はディレクトリ /home/greg と /home/other に同時に存在できますが、2 つの foo.txt ファイルが同じディレクトリに存在することはできません。さらに、ディレクトリ /home/greg の外にある
foo.txt ファイルにアクセスする場合、/home/greg/foo.txt を取得するには、ファイル名の前にディレクトリ名とディレクトリ区切り文字を置く必要があります。プログラミングの分野に適用されるこの原則は、名前空間の概念です。
PHP 名前空間は、次の 2 種類の問題を解決できます:
1. ユーザーが作成したコードと、PHP の内部クラス/関数/定数またはサードパーティのクラス/関数/定数の間の名前の競合。 2. ソース コードの可読性を向上させるために、非常に長い識別子名 (通常は最初の種類の問題を軽減するために定義される) のエイリアス (または短い) 名を作成します。
名前空間を定義する
デフォルトでは、PHP が名前空間をサポートする前と同様に、すべての定数、クラス、関数名はグローバル空間に配置されます。
名前空間はキーワード namespace で宣言されます。ファイルに名前空間が含まれている場合は、他のすべてのコードの前に名前空間を宣言する必要があります。
構文は次のとおりです:
<?php
// 定义代码在 'MyProject' 命名空间中
namespace MyProject;
// ... 代码 ...
?>
你也可以在同一个文件中定义不同的命名空间代码,如:
<?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(); } ?>そして、次のコードはエラーを報告します
<html> <?php namespace MyProject; // 命名空间前出现了“<html>” 会致命错误 - 命名空间必须是程序脚本的第一条语句 ?>
サブネームスペースは、ディレクトリやファイル、PHPネームスペースに非常に似ています。階層的な名前空間名を指定することもできます。したがって、名前空間名は階層的な方法で定義できます。
<?php namespace MyProject\Sub\Level; //声明分层次的单个命名空间 const CONNECT_OK = 1; class Connection { /* ... */ } function Connect() { /* ... */ } ?>
上の例では、定数 MyProjectSubLevelCONNECT_OK、クラス MyProjectSubLevelConnection、および関数 MyProjectSubLevelConnect を作成します。
名前空間の使用法 名前空間の使用方法について説明する前に、PHP がどの名前空間要素を使用するかをどのように認識するかを理解する必要があります。 PHP 名前空間とファイル システムの間で簡単に類推できます。ファイル システム内のファイルにアクセスするには、次の 3 つの方法があります: 1. foo.txt などの相対ファイル名形式。これは currentdirectory/foo.txt として解析されます。ここで、currentdirectory は現在のディレクトリを表します。したがって、現在のディレクトリが /home/foo の場合、ファイル名は /home/foo/foo.txt に解決されます。 2. 相対パス名は、subdirectory/foo.txt の形式です。これは currentdirectory/subdirectory/foo.txt として解析されます。 3. 絶対パス名は /main/foo.txt の形式です。これは /main/foo.txt として解析されます。 PHP 名前空間の要素も同じ原則を使用します。たとえば、クラス名は 3 つの方法で参照できます: 1. 非修飾名、または $a=new foo() や foo::staticmethod() などの接頭辞 のないクラス名。 ;。現在の名前空間が currentnamespace の場合、foo は currentnamespacefoo に解決されます。 foo を使用するコードがグローバルであり、どの名前空間にもコードが含まれていない場合、foo は foo として解決されます。 警告: ネームスペース内の関数または定数が未定義の場合、修飾されていない関数または定数名はグローバル関数または定数名に解決されます。 2. 修飾名、またはプレフィックス を含む名前 ($a = new subnamespacefoo(); または subnamespacefoo::staticmethod(); など)。現在の名前空間が currentnamespace の場合、foo は currentnamespacesubnamespacefoo に解決されます。 foo を使用するコードがグローバルであり、コードがどの名前空間にも含まれていない場合、foo はサブ名前空間 foo に解決されます。 3. 完全修飾名、またはグローバル接頭辞演算子を含む名前たとえば、$a = new currentnamespacefoo(); または currentnamespacefoo::staticmethod(); です。この場合、foo はコード内で常にリテラル名 currentnamespacefoo に解決されます。 これら 3 つのメソッドの使用例を次に示します。 Example Example グローバル クラス、関数、または定数にアクセスするには、完全修飾名を使用できることに注意してください。 strlen()、例外、INI_ALL など。 名前空間内のグローバル クラス、関数、定数にアクセスします: 名前空間と動的言語機能 PHP の名前空間の実装は、言語自体の動的機能の影響を受けます。したがって、以下のコードを名前空間に変換する場合は、要素に動的にアクセスします。 インスタンス プログラムの実行結果: classname::__construct
関数名
global 完全修飾名 (名前空間プレフィックスを含むクラス名) を使用する必要があります。動的クラス名、関数名、または定数名では修飾名と完全修飾名に違いがないため、先頭のバックスラッシュは不要であることに注意してください。 インスタンス 名前空間の要素への動的アクセス プログラムの実行結果: classname::__construct
関数名
グローバル
クラス名::__construct
関数名
グローバル
名前空間名クラス名::__construct
名前空間名クラス名::__construct
名前空間名機能名
名前空間名機能名
名前空間付き
namespaced namespaceキーワードと__NAMESPACE__定数 PHPは、現在の名前空間内の要素にアクセスする2つの抽象メソッド、__NAMESPACE__マジック定数とnamespaceキーワードをサポートしています。 定数 __NAMESPACE__ の値は、現在の名前空間の名前を含む文字列です。どの名前空間にも含まれていないグローバル コードには、空の文字列が含まれます。 例 __NAMESPACE__ 例、名前空間内のコード プログラムの実行結果: "MyProject" Example __NAMESPACE__ 例、グローバルコード プログラムの実行結果: "" インスタンス 定数 __NAMESPACE__ は、名前を動的に作成する場合に便利です。例: __NAMESP を使用します。動的に作成する ACE__ 名前 キーワード名前空間を使用すると、現在の名前空間またはサブ名前空間内の要素に明示的にアクセスできます。これは、クラスの self 演算子に相当します。 インスタンス 名前空間演算子、名前空間内のコード インスタンス 名前空間演算子、グローバルコード 名前空間を使用: alias/import PHP 名前空間は 2 つをサポートしますエイリアスまたはインポートの使用方法: クラス名にエイリアスを使用するか、名前空間名にエイリアスを使用します。 PHP は関数や定数のインポートをサポートしていないことに注意してください。 PHP では、エイリアスは use 演算子を使用して実装されます。次の 3 つのインポート方法をすべて使用します。 1. use 演算子を使用してエイリアスをインポート/使用します。行には複数の use ステートメントが含まれています 3. インポートと動的名 4. インポートと完全修飾名 名前空間の使用: フォールバック グローバル関数/定数 PHP は、名前空間内で修飾されていないクラス、関数、または定数の名前を検出すると、別の優先順位戦略を使用して名前を解決します。クラス名は常に現在の名前空間内の名前に解決されます。したがって、システム内のクラス名、または名前空間に含まれていないクラス名にアクセスする場合は、完全修飾名 を使用する必要があります。 例: 1. 名前空間内のグローバル クラスにアクセスします 関数と定数の場合、関数または定数が現在の名前空間に存在しない場合、PHP はグローバル空間で関数または定数を使用するようにフォールバックします。 2. 名前空間のグローバル関数/定数をバックアップします グローバル空間 名前空間が定義されていない場合、すべてのクラスと関数はグローバル空間で定義されます。 PHP に名前空間の概念が導入される前と同じです。名前に接頭辞を付けると、その名前が別の名前空間にある場合でも、その名前がグローバル空間にあることを示します。 例 グローバル空間記述の使用 名前空間の順序 名前空間が作成されると、最もエラーが発生しやすいのは、クラスを使用するとき、この検索パスですクラスはどんな感じですか? 名前解決は次の規則に従います: 1. 完全修飾名を持つ関数、クラス、および定数の呼び出しはコンパイル時に解決されます。たとえば、新しい AB はクラス AB に解決されます。 2. すべての非修飾名と修飾名 (非完全修飾名) は、現在のインポート ルールに従ってコンパイル時に変換されます。たとえば、名前空間 ABC が C としてインポートされた場合、CDe() の呼び出しは ABCDe() に変換されます。 3. 名前空間内では、インポート ルールに従って変換されないすべての修飾名の前に現在の名前空間名が付きます。たとえば、CDe() が名前空間 AB 内で呼び出された場合、CDe() は ABCDe() に変換されます。 4. 修飾されていないクラス名は、現在のインポート ルールに従ってコンパイル時に変換されます (短いインポート名の代わりに完全な名前が使用されます)。たとえば、名前空間 ABC が C としてインポートされる場合、 new C() は new ABC() に変換されます。 5. 名前空間 (例: AB) 内では、非修飾名への関数呼び出しは実行時に解決されます。たとえば、関数 foo() の呼び出しは次のように解析されます: 1. 現在の名前空間で ABfoo() という名前の関数を見つけます 2. グローバル空間で関数 foo() を見つけて呼び出してみます。 6. 名前空間 (AB など) 内の非修飾名または修飾名クラス (非完全修飾名) への呼び出しは実行時に解決されます。以下は、new C() と new DE() を呼び出す解析プロセスです。 new C() の解析: 1. 現在の名前空間で ABC クラスを検索します。 2. クラス ABC を自動ロードしてみます。 new DE(): の分析 3. クラス名の前に現在の名前空間名を追加して ABDE となり、クラスを検索します。 4. クラス ABDE を自動ロードしてみます。 グローバル名前空間内のグローバル クラスを参照するには、完全修飾名 new C() を使用する必要があります。 <?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
?>
<?php
namespace MyProject;
header("Content-type:text/html;charset=utf-8"); //设置编码
echo '"', __NAMESPACE__, '"'; // 输出 "MyProject"
?>
<?php
header("Content-type:text/html;charset=utf-8"); //设置编码
echo '"', __NAMESPACE__, '"'; // 输出 "MyProject"
?>
<?php
namespace MyProject;
function get($classname)
{
$a = __NAMESPACE__ . '\' . $classname;
return new $a;
}
?>
<?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
?>
<?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 对象
?>
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // 实例化 My\Full\Classname 对象
NSname\subns\func(); // 调用函数 My\Full\NSname\subns\func
?>
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // 实例化一个 My\Full\Classname 对象
$a = 'Another';
$obj = new $a; // 实际化一个 Another 对象
?>
<?php
use My\Full\Classname as Another, My\Full\NSname;
$obj = new Another; // instantiates object of class My\Full\Classname
$obj = new \Another; // instantiates object of class Another
$obj = new Another\thing; // instantiates object of class My\Full\Classname\thing
$obj = new \Another\thing; // instantiates object of class Another\thing
?>
<?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
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
namespace A\B\C;
/* 这个函数是 A\B\C\fopen */
function fopen() {
/* ... */
$f = \fopen(...); // 调用全局的fopen函数
return $f;
}
?>