PHP关键特性之命名空间实例详解
命名空间主要是为了解决代码中类和函数可能存在冲突的问题,而这个特性其他语言一早就有,PHP则是姗姗来迟,它的出现催生了PSR-4的诞生,从而也催生了Composer的兴起,所以是非常重要的特性。
命名空间的定义
命名空间是一个容器,这个容器主要是为了识别其下的类和函数。一旦定义了命名空间,它下面的代码就属于这个命名空间了,所以命名空间的定义要在代码的最开始行。
对于同一个包来说,同一个命名空间或者子命名空间的代码没有必要在一个PHP文件中定义,子命名空间下的代码是为了完成特定模块的工作,组合起来就是一个包完整的命名空间。
假如编写的代码没有定义命名空间,那说明它属于全局的命名空间(\符号),所以能够直接引用类或者函数(不用添加\符号)。
引用命名空间标识符的三种方式
(1)Fully-qualifiedname
类似于操作系统上的绝对路径,而且是完整的路径,所以在理解的时候不会有误解。
比如在new\A\B\C,那么C就被会解析到A\B命名空间下的C类。
(2)Qualifiedname
类似于操作系统上的相对路径,它包含部分名字并被引用到当前的命名空间。
比如B\C()在命名空间A下调用,则最终引用的命名空间就是A\B\C()。
(3)Unqualifiedname
类似于Qualifiedname,但是没包括子命名空间。
比如C()在命名空间A\B下调用,则最终引用的命名空间就是A\B\C()。
通过一个例子来说明三种引用方式:
namespace\Example;
require_once"fnction.php";
classClassA{}
functionFunction(){}
//完全限定名称
\Example\Function();
\Example\B\Function();
//限定名称
B\Function();//指向\Example\B\Function();
//非限定名称
$test=newClassA();//resolvesto\Example\ClassA
Function();//指向\Example\Function
注意:
•Insideanamespace,假如在currentscope没有发现函数和常量的定义,PHP不会报错。而是去全局命名空间中寻找。
•Insideanamespace,假如在currentscope没有发现类的定义,则PHP会直接报错,不会去全局域中找对应的类,所以假如你需要引用一个internal或用户自定义的类,必须使用完全限定名称。
先举个简单的例子,首先编写一段代码(定义在命名空间下),命名为function.php:
namespaceFoo\Bar\subnamespace;
constFOO=1;
functionfoo()
{
return"foo\r\n";
}
classfoo
{
staticfunctionstaticmethod()
{
return__METHOD__."\r\n";
}
functionfoofunction()
{
return__METHOD__."\r\n";
}
}
再编写一段代码test.php,也是处于命名空间之下的代码:
namespacesecondsp;
include'function.php';
classfoo
{
functionfoofunction()
{
return__METHOD__."\r\n";
}
}
functionis_file($file)
{
returntrue;
}
//非限定名称:实例化secondsp\foo类对象
$obj=newfoo;
echo$obj->foofunction();
//实例化Foo\Bar\subnamespace\foo类对象
$obj=newFoo\Bar\subnamespace\foo;
echo$obj->foofunction();
//代码会报错,在命名空间内部,假如无法找到当前命名空间下的类,则会报错
//$obj=newArrayObject(array(1));
$obj=new\ArrayObject(array(1));
//在命名空间内部,假如无法找到当前命名空间下的函数或者常量,则会寻找nativefunction
echostrlen("nihao");
//引用当前命名空间下的函数
var_dump(is_file('nihao'));//True
//引用全局函数
var_dump(\is_file('nihao'));//False
导入,别名
假如要使用的命名空间层级很长且数量很多,那么在使用的时候特别麻烦,所以可以使用use关键字导入命名空间、类、常量、函数等,然后可以使用它们直接引用完整的名称。而alias关键字可以给导入的类和函数等重命名。
举个例子如何使用use关键字,该代码处于全局命名空间之下:
include'function.php'; useFoo\Bar\subnamespace\foo; $obj=newfoo; echo$obj->foofunction(); useFoo\Bar\subnamespace\fooasaliasfunname; $obj=newaliasfunname; echo$obj->foofunction(); useFoo\Bar\subnamespace; $obj=newsubnamespace\foo; echo$obj->foofunction(); useFoo\Bar\subnamespaceasaliasname; $obj=newaliasname\foo; echo$obj->foofunction(); //由于调用代码并不在命名空间内,所以对于全局的类,无需引入使用 $obj=newArrayObject(array(1)); //导入一个函数 usefunctionFoo\Bar\subnamespace\foo; echofoo(); usefunctionFoo\Bar\subnamespace\fooasfunc; echofunc(); useconstFoo\Bar\subnamespace\FOO; //echoFOO;
总结:
•和Python不一样,PHP中的命名空间是语义上的一种概念,和具体代码的位置、布局没有关系,换句话说,使用命名空间的代码需要自己引入库文件(所有文件),至于库文件如何组织无所谓;而在Python中,假如模块或包中有一个__init__.py文件,则Python解析器会自动引入包或所有模块的文件。
•PHP中作用域的概念很弱化,全局域和局部域分的很清楚,比如在函数或类中无法引用全局空间中的变量。而在命名空间则不同,定义命名空间的代码,假如找不到对应命名空间下的常量和函数,则会使用全局的常量和函数;而假如找不到对应名命名空间下的类(包括自定义类),则代码直接报错。
•通过use关键字使用命名空间的,无须通过完全限定名称的方式(\符号)导入,因为PHP已经假设导入的是完全限定的命名空间。
•通过use关键字可以导入常量、函数、类、接口、其他命名空间。
•命名空间是一种语言特性,为了追求更有效的使用,应该有一种使用规范和自动加载机制,这就是PSR-4规范。
以上所述是小编给大家介绍的PHP关键特性之命名空间实例详解,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!