ホームページ  >  記事  >  バックエンド開発  >  ネームスペースとは何ですか? PHPの名前空間の詳しい説明

ネームスペースとは何ですか? PHPの名前空間の詳しい説明

怪我咯
怪我咯転載
2017-06-14 11:49:586026ブラウズ

名前空間とは何ですか?この記事では、PHP の名前空間について詳しく説明します。お役に立てば幸いです。

ネームスペースとは何ですか? PHPの名前空間の詳しい説明

名前空間とは何ですか?

広い意味では、名前空間は物事をカプセル化する方法であり、この抽象的な概念は多くの場所で見ることができます。たとえば、ディレクトリはオペレーティング システムで関連ファイルをグループ化するために使用され、ディレクトリ内のファイルの名前空間として機能します。

簡単な例として、ファイル foo.txt はディレクトリ /home/greg と /home/other に同時に存在できますが、2 つの foo.txt ファイルが同じディレクトリに存在することはできません。また、ディレクトリ /home/greg の外にある foo.txt ファイルにアクセスする場合は、/home/greg/foo.txt のように、ファイル名の前にディレクトリ名とディレクトリ区切り文字を置く必要があります。この原理をプログラミングの分野に適用したのが、名前空間の概念です。

名前空間の定義

PHP の名前空間は、C++ を知っている人にとっては新しいものではありません。ただし、PHP では名前空間は依然として非常に重要です。

PHP 名前空間は、次の 2 種類の問題を解決できます。

  • ユーザーが作成したコードと PHP の内部クラス/関数/定数またはサードパーティのクラス/関数/定数の間の名前の競合

  • が非常に長いソース コードの可読性を向上させるための、識別子の別名 (または短い) 名 (最初の種類の問題を軽減するために定義されることがよくあります)。

1) 名前空間を定義します (キーワード名前空間を使用します)

正当な PHP コードを名前空間に含めることができますが、クラス (抽象クラスと特性を含む)、インターフェイス、関数、定数などのみを含めることができます。型のコードは名前空間の影響を受けます。

名前空間の定義は、キーワード namespace を使用して宣言する必要があります。構文形式は次のとおりです。

namespace 命名空间名;

[例] 名前空間を定義する方法を示します:

<?php
    namespace MyProject;    // 定义名为 MyProject 的命名空间。
    const CONNECT_OK = 1;
    class Myclass {
        /* ... */
    }
    function Myfunc() {
        /* ... */
    }
?>

宣言する前にソース ファイルのエンコーディングを定義することに加えて、名前空間 この方法の宣言ステートメントを除き、PHP 以外のすべてのコード (空白を含む) を名前空間宣言の前に置くことはできません。

さらに、PHP の他の言語機能とは異なり、同じ名前空間を複数のファイルで定義できるため、同じ名前空間の内容を別のファイルに分割して保存することができます。

2) サブ名前空間を定義する

ディレクトリやファイルとの関係と同様に、PHP の名前空間でも階層的な名前空間名を指定できます。したがって、名前空間の名前は階層的に定義できます:

namespace App\Model;
namespace App\Controller\Home;

[例] サブ名前空間を定義します:

<?php
    namespace MyProject\Controller\Home;    // 定义名为 MyProject 的命名空间。
    const CONNECT_OK = 1;
    class Myclass {
        /* ... */
    }
    function Myfunc() {
        /* ... */
    }
?>

3) 同じファイル内に複数の名前空間を定義します

1つのファイルでも複数の名前空間を定義できます同じファイル内で複数の名前空間を定義するには 2 つの構文形式があります。以下にその例を示します:

[例] 複数の名前空間を定義する - 単純な組み合わせ構文。

<?php
    namespace MyProject;
    const CONNECT_OK = 1;
    class className {
        /* ... */
    }
    namespace AnotherProject;
    const CONNECT_OK = 1;
    class className {
        /* ... */
    }
?>

[例] 複数の名前空間を定義する - 中括弧 { } 構文。

<?php
    namespace MyProject{
        const CONNECT_OK = 1;
        class className {
            /* ... */
        }
    }
    namespace AnotherProject{
        const CONNECT_OK = 1;
        class className {
            /* ... */
        }
    }
?>

実際のプログラミングの実践では、同じファイル内で複数の名前空間を定義することはお勧めできません。複数の名前空間の定義は、主に、同じファイル内の複数の PHP スクリプトを結合するために使用されます。複数の名前空間を定義する場合は、中括弧構文を使用することをお勧めします。

グローバル非名前空間のコードを名前空間のコードと組み合わせるには、中括弧の形式でのみ構文を使用できます。同時に、グローバル コードは名前と名前を付けずに名前空間ステートメントで囲む必要があります。中かっこは次のようになります。 表示:

<?php
    namespace MyProject{        // 命名空间中的代码
        const CONNECT_OK = 1;
        class className {
            /* ... */
        }
    }
    namespace {                 // 命名空间外的全局代码
        $obj = new MyProject\className();
    }
?>

名前空間の使用: 基本

名前空間の使用方法について説明する前に、どの名前空間要素を使用するかを PHP がどのように認識するかを理解する必要があります。 PHP 名前空間とファイル システムを簡単に例えることができます。ファイル システム内のファイルにアクセスするには、次の 3 つの方法があります:

  • foo.txt などの相対ファイル名形式。これは currentdirectory/foo.txt として解析されます。ここで、currentdirectory は現在のディレクトリを表します。したがって、現在のディレクトリが /home/foo の場合、ファイル名は /home/foo/foo.txt として解析されます

  • 相対パス名の形式は、サブディレクトリ/foo.txt のようになります。これは、/main/foo.txt などの currentdirectory/subdirectory/foo.txt

  • 絶対パス名形式として解析されます。これは /main/foo.txt として解析されます。

PHP 名前空間の要素も同じ原則を使用します。たとえば、名前空間内のクラス名は、

  • 非修飾名、または $a=new foo();foo::staticmethod(); などのプレフィックスを含まないクラス名という 3 つの方法で参照できます。現在の名前空間が currentnamespace の場合、foo は currentnamespacefoo に解決されます。 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 总是被解析为代码中的文字名 currentnamespace\foo。

警告:如果命名空间中的函数或常量未定义,则该非限定的函数名称或常量名称会被解析为全局函数名称或常量名称。

下面是一个使用这三种方式的实例,我们需要两个 PHP 源文件,分别是 demo.php 和 index.php,示例代码如下:

1) demo.php

<?php
    namespace Foo\Bar\Demo;
    const FOO = 1;
    function foo() {}
    class foo
    {
        public function demo() {
            echo &#39;命名空间为:Foo\Bar\Demo&#39;;
        }
    }
?>

2) index.php

<?php
    namespace Foo\Bar;
    include &#39;Demo.php&#39;;
    const FOO = 2;
    function foo() {
        echo &#39;Foo\Bar 命名空间下的 foo 函数<br>&#39;;
    }
    class foo
    {
        static function demo(){
            echo &#39;命名空间为:Foo\Bar<br>&#39;;
        }
    }
    /* 非限定名称 */
    foo();                  // 解析为 Foo\Bar\foo resolves to function Foo\Bar\foo
    foo::demo();            // 解析为类 Foo\Bar\foo 的静态方法 staticmethod。
    echo FOO.&#39;<br>&#39;;        // 解析为常量 Foo\Bar\FOO
    /* 限定名称 */
    Demo\foo();             // 解析为函数 Foo\Bar\Demo\foo
    Demo\foo::demo();       // 解析为类 Foo\Bar\Demo\foo,
                            // 以及类的方法 demo
    echo Demo\FOO.&#39;<br>&#39;;   // 解析为常量 Foo\Bar\Demo\FOO
                                     
    /* 完全限定名称 */
    \Foo\Bar\foo();         // 解析为函数 Foo\Bar\foo
    \Foo\Bar\foo::demo();   // 解析为类 Foo\Bar\foo, 以及类的方法 demo
    echo \Foo\Bar\FOO.&#39;<br>&#39;; // 解析为常量 Foo\Bar\FOO
?>

运行结果如下:

Foo\Bar 命名空间下的 foo 函数
命名空间为:Foo\Bar
2
Foo\Bar\Demo 命名空间下的 foo 函数
命名空间为:Foo\Bar\Demo
1
Foo\Bar 命名空间下的 foo 函数
命名空间为:Foo\Bar
2

注意:访问任意全局类、函数或常量,都可以使用完全限定名称,例如 \strlen() 或 \Exception 等。

使用命名空间:别名/导入

PHP 允许通过别名引用或导入的方式来使用外部的命名空间,这是命名空间的一个重要特征。这有点类似于在类 unix 文件系统中可以创建对其它的文件或目录的符号连接。

使用 use 关键字可以实现命名空间的导入,从 PHP5.6 开始允许导入函数和常量,并为它们设置别名。语法格式如下:

use namespace;

在 PHP 中,别名是通过操作符 use 与 as 来实现的,语法格式如下:

use 命名空间 as 别名;

【示例】使用 use 操作符导入和使用别名。

<?php
    namespace foo;
    use My\Full\Classname as Another;
    // 下面的例子与 use My\Full\NSname as NSname 相同
    use My\Full\NSname;
    // 导入一个全局类
    use ArrayObject;
    // 导入一个函数
    use function My\Full\functionName;
    // 导入一个函数并定义别名
    use function My\Full\functionName as func;
    // 导入一个常量
    use const My\Full\CONSTANT;
    $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 对象
    func();                         // 调用 My\Full\functionName 函数
    echo CONSTANT;                  // 打印 My\Full\CONSTANT 常量
?>

注意:对命名空间中的名称(包含命名空间分隔符的完全限定名称,如 Foo\Bar ,以及相对的不包含命名空间分隔符的全局名称,如 FooBar)来说,前导的反斜杠是不必要的也是不推荐的,因为导入的名称必须是完全限定的,不会根据当前的命名空间作相对解析。

为了简化操作,PHP 还支持在一行中导入多个命名空间,中间使用,隔开,示例代码如下:

<?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 = &#39;Another&#39;;
    $obj = new $a;      // 实际化一个 Another 对象
?>

另外,导入操作只影响非限定名称和限定名称。完全限定名称由于是确定的,故不受导入的影响。

namespace 关键字和 __NAMESPACE__ 常量

PHP 支持两种抽象的访问当前命名空间内部元素的方法,__NAMESPACE__ 魔术常量和 namespace 关键字。

__NAMESPACE__ 常量的值是包含当前命名空间名称的字符串。在全局的,不包括在任何命名空间中的代码,它是一个空的字符串。示例代码如下:

<?php
    namespace App\Controller\Home;
    echo __NAMESPACE__;
?>

运行结果如下:

App\Controller\Home

namespace 关键字可用来显式访问当前命名空间或子命名空间中的元素,它等价于类中的 self 操作符。示例代码如下:

<?php
    namespace MyProject;
    use Foo\Bar\Demo as demo;       // 导入 Foo\Bar\Demo 命名空间
    blah\mine();                    // 调用 MyProject\blah\mine() 函数
    namespace\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
?>

命名空间名称解析规则

在说明名称解析规则之前,我们先来看看命名空间名称的定义:

  • 非限定名称:名称中不包含命名空间分隔符的标识符,例如 Foo;

  • 限定名称:名称中含有命名空间分隔符的标识符,例如 Foo\Bar;

  • 完全限定名称:名称中包含命名空间分隔符,并以命名空间分隔符开始的标识符,例如 \Foo\Bar。namespace\Foo 也是一个完全限定名称。

名称解析遵循下列规则:

  • 関数、クラス、定数の完全修飾名への呼び出しはコンパイル時に解決されます。たとえば、新しい 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() を使用する必要があります。

推奨学習:「PHPビデオチュートリアル

以上がネームスペースとは何ですか? PHPの名前空間の詳しい説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はbiancheng.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。