PHP命名空间
Posted 寻觅beyond
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP命名空间相关的知识,希望对你有一定的参考价值。
问题引出:通常用include包含文件的时候,包含的文件中包含同名的类(包括trait)、接口、函数、常量,比如下面的例子:
运行C.php会出错,因为在同一个文件中包含了相同的类名的类
使用命名空间的意义:可以理解为--->使用类似文件系统分级的形式,在定义类或者函数的时候,指定该类或者该函数所在的文件目录即可
按照上面的理解,先假设有一个类名为Test的类在dir1目录下,另外一个类名也为Test的类在dir2目录下,然后我们在使用其中dir1下的Test类的时候,在类名前面要加上dir1,以dir1\\Test的形式实例化;同样,如果要使用dir2下的Test类的时候,就在类名前加上dir2,以dir2\\Test的形式实例化。
上面的dir1或dir2就是PHP中的命名空间,命名空间的层级结构(方便理解的话,可以理解为层级结构)使用反斜线(\\),也就是windows下的文件系统的分隔符来分隔。
上面的例子代码如下:
这样运行C.php就不会出错了,因为两个同名的类存在不同的命名空间,所以不会产生冲突
到这里,其实命名空间的原理已经讲清楚了。但是每次实例画一个类的时候,都写那么一长串命名空间,比较麻烦,所以可以使用关键字use,在实例画一个类的之前,先使用use将这个类的完整命名空间及类型指明,然后就可以直接使用类名实例化对象了。比如下面的例子
这个时候实例化的是dir1命名空间下的Test类,如果又想导入dir2命名空间下的Test类,再使用use dir2\\Test的就会出现最初说的那个问题-->同一个作用域,有两个完全相同的类名,出错。
解决方法是在use命名空间下的类之后,给该类取一个别名,之后使用别名来实例化类就可以了,如下面的例子
以上的对于类的用法同样也适用于函数、接口、常量。
但是要注意是,
在使用use导入类或者接口的时候,格式为use namespace\\className ,use 后面直接加上命名空间以及类名或者接口名即可。
在使用use导入函数的时候,格式为use function namespace\\funcName ,use 后面要加上关键字function才行。
在使用use导入常量的时候,格式为use const namespace\\funcName ,use 后面要加上关键字const才行。
命名空间分为全局空间和命名空间,使用namespace声明的空间称为命名空间,如上面的A.php中的dir1命名空间和B.php中的dir2命名空间。而没有在脚本中指定命名空间的时候,就属于全局空间,如C.php。
所以 以上的内容是在全局空间去调用命名空间的类或者函数。
看下面这个例子:
这个例子中,x.php中的Test类因为没有使用namespace声明命名空间,所以Test属于全局空间,访问全局访问全局空间的类时,要使用"\\",再加上要实例化的类,"\\"可以理解为“根目录”。
注意这里很容易产生误解,比如上图中的y.php中,先声明了index的命名空间,然后在将x.php包含进来,此时不要认为x.php中的内容就变成了index命名空间中声明的了,正确的理解是,x.php中的内容仍旧是在x.php中定义,不可以理解为将x.php中的代码粘贴到y.php中index命名空间下。
还有一个要注意的是,对于类来说,使用全局空间的类,要使用反斜线"\\",如果不加反斜线,解释器就理解为实例化在当前命名空间中定义的类,如果当前命名空间未定义该类,则直接报错,停止运行;
在使用全局的函数或者常量的时候,可以不用加"\\",通常是这个过程,首先,会在当前的命名空间中寻找是否定义了该函数或者常量,如果定义了,则直接只用命名空间中的函数或者常量,不再往外层继续寻找;如果当前的命名空间中没有定义该常量或者函数时,就会去寻找全局空间,也就是"\\"中是否存在该函数或者常量,如果存在,就是用全局空间中的该函数或者常量,如果不存在,则报错。结合上面一个例子和下面这个例子理解。
以上是关于PHP命名空间的主要内容,如果未能解决你的问题,请参考以下文章