命名空间 - 类的查找规则

  • 作者:KK

  • 发表日期:2018.8.12


完整类名查找

在一个命名空间下 new 另一个空间下的类,最基本的写法就是写成new \a\b\Test()这样在 new 类名的时候把类名带上命名空间,其实这就是完整类名。测试代码:

namespace x\y;

class Z{
    public function getTest(){
        return new \a\b\Test();
    }
}

以上代码就是在x\y\Z这个类的一个方法里初始化了另一个命名空间类。


相对空间查找

先看以下代码:

namespace x\y;

class Z{
    public function getTest(){
        return new Test();
    }
}

上面的代码 new 的时候只是写了类名,这样引系统查找x\y\Test这个类,因为当前命名空间是x\y,而且 new 的时候也没说明要从哪个命名空间开始。

其实就像是在 a\b 目录下说要找 c.php 文件一样,那系统理解为在当前目录开始查找,基于当前目录进行相对路径处理。


new 自带的类

我们最经常要初始化PHP的几个自带类,比如下面这三个,初始化的时候前面要带一个\

namespace xxx;

class Z{
    public function getTest(){
        return new \PDO();
        return new \Exception();
        return new \stdClass();
    }
}

这是为什么呢?因为如果不带\号的话,就会变成相对空间查找,于是系统会报错说找不到xxx\PDO这个类的,我已经说过,命名空间就是一个 树状空间 空间,没有命名空间的类就是挂在根目录下的,你要 new 它的话,前面加个\号就是说从根目录开始找这个类了,也就是\PDO指向了根目录空间的PDO类。


use 先引用,然后直接 new 类名

你会看到一些开源框架或别人的代码都是这样写的:

namespace app\controllers;

use lib\Pagination;

class ControllerA{
    public function test(){
        $pagination = new Pagination();
        //...
    }
}

这代码也很容易理解,在namespace语句下面的use语句先引用了某个命名空间下的类,而 new 的时候就直接写类名就可以了,系统会优先看看有没有 use ,没有 use 再到空间里查找这个类。

而另外,use语句所引用的类描述的空间类名,总是相对于根空间的use \lib\Pagination这样在lib前面加一个\号是很多余的(比如也有一些use \stdClass),你会看到那些开源框架根本不会傻乎乎地这样写,这样只会显示了你对命名空间的基本知识并不了解。