1.1.1. 09.命名空间


命名空间简单来说就是为了解决命名重复而造成的系统冲突。其思想来源于文件路径,"同一路径下不能存在相同名称的文件"。 如 www/a、www/b 可以同时存在,www/a/c、www/b/c 也可以同时存在。

1.定义命名空间

命名空间由关键字 namespace 定义。 其必须在程序脚本的第一条语句,否则会报致命错误。除 declare 之外。

<?php
    namespace App;

    const CONNECT_OK = 1;

子命名空间,中间由 \ 隔开

<?php
    namespace App\Models;

    class Product extends Model{
        // ***
    }

2.同一文件定义多个命名空间

<?php
    namespace MyProject{
        const CONNECT_OK = 1;
        class Connection { /* ... */ }
        function connect() { /* ... */  }
        }
    }

    namespace AnotherProject{
        const CONNECT_OK = 1;
        class Connection { /* ... */ }
        function connect() { /* ... */  }
        }
    }

3.命名空间基础:命名空间与路径类似,分为非限定名称、限定名称、完全限定名称。

  • 非限定名称,不加前缀的名称,如 $a = new foo(), foo::staticmethod()。如果当前命名空间是 currentnamespace,则 foo 就会被解析成 currentnamespace\foo。
  • 限定名称,包含前缀的名称,如 $a = new subnamespace\foo(),或 subnamespace\foo::staticmethod()。如果当前命名空间为 currentnamespace,则会被解析为 currentnamespace\subnamespace\foo。
  • 完全限定名称,如 $a = new currentnamespace\subnamespace\foo(), currentnamespace\subnamespace\foo::staticmethod()。
// file1
<?php
    namespace currentnamespace;

    class foo{
        public static staticmethod(){
            \\ ***
        }
    }
?>

// file2
<?php
    namespace currentnamespace\subnamespace;

    class foo{
         public static staticmethod(){
                \\ ***
            }
    }
?>

// file3
<?php 
    namespace currentnamespace;

    $a = new foo();  // 非限定名称,解析 currentnamespace\foo
    foo::staticmethod(); // 非限定名称,解析 currentnamespace\foo

    $b = new subnamespace\foo(); // 限定名称,解析 currentnamespace\subnamespace\foo
    subnamespace\foo::staticmethod(); // 限定名称,解析 currentnamespace\subnamespace\foo

    $c = new currentnamespace\subnamespace\foo(); // 完全限定名称
    currentnamespace\subnamespace\foo::staticmethod(); // 完全限定名称

4.namespace 与 NAMESPACE

常量 NAMESPACE 表示当前的命名空间,如果在全局中,则返回一个空字符串。 关键字 namespace 可用来显式访问当前命名空间或子命名空间中的元素。它等价于类中的 self 操作符。

5.别名与导入

使用 use 关键字来导入命名空间 使用 as 关键字来给命名空间取别名,可以给类、接口、命名空间使用别名。

<?php
    namespace foo;
    use My\Full\Classname as Another; // 引入 My\Full\Classname 类并取别名为 Another

    use function My\Full\functionName as func; // 引入函数  My\Full\functionName 并取别名为 func。

    use const My\Full\CONSTANT; // 引入常量

    $obj = new namespace\Another; // 实例化 foo\Another 对象
    $obj = new Another; // 实例化 My\Full\Classname 对象
    func(); // calls function My\Full\functionName
    echo CONSTANT; // echoes the value of My\Full\CONSTANT

6.全局命名空间

如果没有定义任何命名空间,则为全局空间,调用时在前面加斜杠 (\)

<?php
    namespace A\B\C;

    /* 这个函数是 A\B\C\fopen */
    function fopen(){
        $f = \fopen(...); // 调用全局的fopen函数
        return $f;
    }

7.名称规则解析

类名称总是会解析到当前命名空间中,如果不存在则需要使用完全限定命名空间。

<?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;
    use B\D, C\E as F;

    // 函数调用
    foo(); // 先尝试在 A 中调用,没有则再尝试在全局中调用。

    \foo(); // 在全局中调用

    my\foo(); // 在 A\my 中调用。

    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"
Copyright © Kagami丶 2019 all right reserved,powered by Gitbook该文件修订时间: 2019-10-17 19:28:55

results matching ""

    No results matching ""