PHP名前空間を完全にマスターする

小云云
リリース: 2023-03-20 20:20:01
オリジナル
1477 人が閲覧しました

名前空間は、ユーザーが作成したコードと PHP の内部クラス/関数/定数またはサードパーティのクラス/関数/定数の間の名前の競合を解決するために使用されます。ソース コードの読みやすさを向上させるために、非常に長い識別子名のエイリアス (または短い) 名を作成します。

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

ファイルに名前空間が含まれている場合は、declare キーワード、ソース ファイルのエンコード方法を定義するために使用される declare ステートメントを除き、他のすべてのコードよりも前に名前空間を宣言する必要があります。空白を含むコードを名前空間宣言の前に置くことはできません。

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

サブ名前空間を定義する

<?phpnamespace MyProject\Sub\Level;const CONNECT_OK = 1;class Connection { /* ... */ }function connect() {/* ... */ }
ログイン後にコピー

同じファイル内で複数の名前空間を定義する

<?phpnamespace MyProject;const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */  }namespace AnotherProject;const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */  }
ログイン後にコピー

この構文を使用して 1 つのファイル内で複数の名前空間を定義することはお勧めできません。次の中括弧形式の構文を使用することをお勧めします。

<?phpnamespace MyProject {const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */  }
}namespace AnotherProject {const CONNECT_OK = 1;class Connection { /* ... */ }function connect() { /* ... */  }
}
ログイン後にコピー

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

グローバル非名前空間のコードを名前空間のコードと組み合わせるには、中括弧の形式でのみ構文を使用できます。グローバル コードは、名前のない名前空間ステートメントを中括弧で囲む必要があります。

クラスは、

  1. 非修飾名、または $ などの接頭辞を含まないクラス名という 3 つの方法で参照できます。 =new foo(); または foo::staticmethod();。現在の名前空間が currentnamespace の場合、foo は currentnamespacefoo に解決されます。 foo を使用するコードがグローバルであり、どの名前空間にもコードが含まれていない場合、foo は foo として解決されます。 警告: 名前空間内の関数または定数が未定義の場合、修飾されていない関数または定数名はグローバル関数または定数名に解決されます。

  2. 修飾名、または接頭辞を含む名前 ($a = new subnamespacefoo();subnamespacefoo::staticmethod(); など)。現在の名前空間が currentnamespace の場合、foo は currentnamespacesubnamespacefoo に解決されます。 foo を使用するコードがグローバルであり、どの名前空間にも含まれていないコードの場合、foo は subnamespacefoo として解決されます。

  3. 完全修飾名、またはグローバル接頭辞演算子を含む名前 (例: $a = new currentnamespacefoo(); または currentnamespacefoo::staticmethod();)。この場合、foo は常にコード currentnamespacefoo 内のリテラル名に解決されます。

グローバル クラス、関数、定数にアクセスするには、strlen()ExceptionINI_ALL などの完全修飾名を使用できることに注意してください。

注: 親ファイルに含まれる子ファイルに含まれるファイルの相対パスは、子ファイル ディレクトリではなく、親ファイル ディレクトリに対するものです。

PHP は、現在の名前空間内の要素にアクセスする 2 つの抽象メソッド、__NAMESPACE__ マジック定数と __NAMESPACE__魔术常量和namespace关键字。

__NAMESPACE__namespace

キーワードをサポートしています。

__NAMESPACE__ は文字列を表すことができ、その他は namespace と同じです。

エイリアスをインポート/使用するには use 演算子を使用します

<?phpnamespace foo;use My\Full\Classname as Another;// 下面的例子与 use My\Full\NSname as NSname 相同use My\Full\NSname;// 导入一个全局类use ArrayObject;// importing a function (PHP 5.6+)use function My\Full\functionName;// aliasing a function (PHP 5.6+)use function My\Full\functionName as func;// importing a constant (PHP 5.6+)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(); // calls function My\Full\functionNameecho CONSTANT; // echoes the value of My\Full
ログイン後にコピー

use 演算子を使用してエイリアスをインポート/使用します。複数の use ステートメントが 1 行に含まれます

<?phpuse My\Full\Classname as Another, My\Full\NSname;$obj = new Another; // 实例化 My\Full\Classname 对象NSname\subns\func(); // 调用函数 My\Full\NSname\subns\func
ログイン後にコピー

インポート名と動的名

インポート操作は実行可能ファイルをコンパイルしていますが、動的クラス名、関数名、または定数名はコンパイルしていません。

<?phpuse My\Full\Classname as Another, My\Full\NSname;$obj = new Another; // 实例化一个 My\Full\Classname 对象$a = &#39;Another&#39;;$obj = new $a;      // 实际化一个 Another 对象
ログイン後にコピー

インポートと完全修飾名

インポート操作は、非修飾名と修飾名のみに影響します。完全修飾名は決定的であるため、インポートの影響を受けません。

<?phpuse 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
ログイン後にコピー

グローバル空間記述を使用する

<?phpnamespace A\B\C;/* 这个函数是 A\B\C\fopen */function fopen() { 
     /* ... */
     $f = \fopen(...); // 调用全局的fopen函数
     return $f;
}
ログイン後にコピー

PHP は、名前空間内で修飾されていないクラス、関数、または定数の名前を検出すると、別の優先順位戦略を使用して名前を解決します。クラス名は常に現在の名前空間内の名前に解決されます。したがって、システムの内部にあるクラス名、または名前空間に含まれていないクラス名にアクセスする場合は、完全修飾名を使用する必要があります。関数と定数の場合、関数または定数が現在の名前空間に存在しない場合、PHP はグローバル空間で関数または定数を使用するようにフォールバックします。
    <?phpnamespace A\B\C;class Exception extends \Exception {}$a = new Exception(&#39;hi&#39;); // $a 是类 A\B\C\Exception 的一个对象$b = new \Exception(&#39;hi&#39;); // $b 是类 Exception 的一个对象$c = new ArrayObject; // 致命错误, 找不到 A\B\C\ArrayObject 类
    ログイン後にコピー
    <?phpnamespace 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_ALLecho strlen(&#39;hi&#39;), "\n"; // 输出 "1"if (is_array(&#39;hi&#39;)) { // 输出 "is not array"
        echo "is array\n";
    } else {    echo "is not array\n";
    }
    ログイン後にコピー
  1. 名前解決は次のルールに従います:

  2. 完全修飾名を持つ関数、クラス、定数の呼び出しはコンパイル時に解決されます。たとえば、新しい AB はクラス AB に解決されます。

    🎜🎜すべての非修飾名と修飾名 (非完全修飾名) は、現在のインポート ルールに従ってコンパイル時に変換されます。たとえば、名前空間 ABC が C としてインポートされる場合、CDe() の呼び出しは ABCDe() に変換されます。 🎜
  3. 在命名空间内部,所有的没有根据导入规则转换的限定名称均会在其前面加上当前的命名空间名称。例如,在命名空间 A\B 内部调用 C\D\e(),则 C\D\e() 会被转换为 A\B\C\D\e() 。

  4. 非限定类名根据当前的导入规则在编译时转换(用全名代替短的导入名称)。例如,如果命名空间 A\B\C 导入为C,则 new C() 被转换为 new A\B\C() 。

  5. 在命名空间内部(例如A\B),对非限定名称的函数调用是在运行时解析的。例如对函数 foo() 的调用是这样解析的:

    1. 在当前命名空间中查找名为 A\B\foo() 的函数

    2. 尝试查找并调用 全局(global) 空间中的函数 foo()。

  6. 在命名空间(例如A\B)内部对非限定名称或限定名称类(非完全限定名称)的调用是在运行时解析的。下面是调用 new C() 及 new D\E() 的解析过程: new C()的解析:

    new D\E()的解析:

    为了引用全局命名空间中的全局类,必须使用完全限定名称 new \C()。

    1. 在类名称前面加上当前命名空间名称变成:A\B\D\E,然后查找该类。

    2. 尝试自动装载类 A\B\D\E。

    3. 在当前命名空间中查找A\B\C类。

    4. 尝试自动装载类A\B\C。

<?phpnamespace 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"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" 中定义的类 "B" 的 "foo" 方法
              // 如果类 "A\B" 未找到,则尝试自动装载类 "A\B"?>
ログイン後にコピー

相关推荐:

PHP命名空间详细使用方法

PHP命名空间、性状与生成器详解

实例详解PHP命名空间用法

以上がPHP名前空間を完全にマスターするの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!