Skip to content

命名空间 ​

命名空间简单的说就是类似文件的路径。为了解决命名冲突的问题产生的。比如在我们的代码中经常遇到以下问题。

自己在一个目录写了一个类叫A. 另外一个人也写了一个类叫A。就会产生一个冲突。最初的框架,比如ci框架,都是类的名字前面加上一CI_的前缀防止命名冲突。

命令空间的思想来源于路径。比如在一个/www/目录下不能存在两个相同的文件。但是可以文件放在/www/a/ 、/www/b下面,这样两个文件就不会冲突。同理命名空间。如果在\www\a\A、\www\b\A 这两个类也可以可以同时存在的。

命名空间的定义使用namespace 定义。只有类(包括抽象类和traits)、接口、函数和常量受到命名空间的影响。

命名空间的定义必须在脚本的首行。不能有bom,否则会出错。

定义子命名空间用\分割。

也可以在一个文件定义多个命名空间。但是一般不这么做。

php
namespace app;
#子命名空间
namespace app\model;


namespace app {
  function test(){}
}
namespace app2{
  function test(){}
}
namespace {
  app\test();
  app2\test();
}

### 命名空间基础

命名空间和路径原理相似。所以有相对、绝对

  • 非限定名称、不包含前缀的类名称。类似a.php 比如include('a.php')

    php
    $a = new Test();// 如果这个文件定义的命名空间是app。那么就是访问的 app\Test类。
  • 限定名称,或包含前缀 类似 文件路径中的 a/c.php这种形式

    php
    $a = new model\Test(); //如果该文件的命名空间是app。则访问的就是app\model\Test
  • 完全限制 类似文件中的绝对路径 /www/a.php

    php
    $a = new \app\Test();

别名和导入 ​

命名空间支持别名和引入外部的名字

所有支持命名空间的PHP版本支持三种别名或导入方式:为类名称使用别名、为接口使用别名或为命名空间名称使用别名

php
namespace a;
use app\model;
use app\test\model as model2;

全局命名空间 ​

如果没有定义任何命名空间,所有的类与函数的定义都是在全局空间,与 PHP 引入命名空间概念前一样。在名称前加上前缀 \ 表示该名称是全局空间中的名称

php
namespace app;

function test(){
  new \Redis();
}

名词解析 ​

php
namespace 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"

基于 VitePress 构建 · 欢迎 Star 与 PR