namespace笔记

namespace的引入是为了解决项目中的重名问题(类、方法、变量等),默认所有的访问都是在当前命名空间下的(如不设置命名空间,则是在全局命名空间下),当产生冲突的时候,就会发生错误,比如File_A中有个test()函数,File_B中也有个test()函数,当把File_A和File_B引入到同一个File_C中的时候,访问test()方法就会出现编译错误,因为不知道要去访问那个test()函数,就像4个人都叫李四,并不知道那个是你找的李四。而给文件设置命名空间之后,我们就可以通过在限定的命名空间下找test()函数,就像找家主A的李四,或者家住B的李四,这样就解决了命名冲突问题。

1.php
1
2
3
4
namespace np_01;
function testMethod() {
echo 'np_01<hr>';
}

2.php
1
2
3
4
5
6
7
namespace np_02;
require_once '1.php';
function testMethod() {
echo 'np_02<hr>';
}
testMethod(); // np_02
\np_01\testMethod(); // np_01
3.php
1
2
3
4
5
6
7
8
9
10
11
12
/*
function var_dump($var) {
echo $var . '<hr>';
}
var_dump('aaaaa'); // 命名冲突
*/
namespace np_03;
function var_dump($var) {
echo $var . '<hr>';
}
var_dump('aaaaa'); // 默认访问当前命名空间np_03的var_dump
\var_dump('aaaa'); // 前置 \ 访问全局命名空间下的var_dump
PHP手册中名称解析规则
  • 完全限定名称的类、方法、常量访问,只单纯按照命名空间解析,不拼接当前命名空间
  • 在命名空间内部,访问非限定名称和非完全限定名称的类、方法、常量,会在前面拼接当前命名空间,然后按照规则3、4进行访问,且如果拼接之后的完整命名空间是new A\B\C\D(),那么它是等价于new \A\B\C\D()
  • 在命名空间内部(比如A\B)访问一个非限定名称方法、常量,那么会先在当前命名空间访问,然后是全局命名空间,比如直接通过var_dump(‘aa’)访问系统函数(如果是非完全限定的,则不会去全局命名空间找,访问不到依然报错,比如\NP\np_02\var_dump())
  • 在命名空间内部(比如A\B)访问一个非限定和非完全限定的类,只会在拼接之后的命名空间中查找,比如new C,是A\B\C,new C\D,则是A\B\C\D,不会在全局命名空间下找,因此在命名空间中访问全局类如new \mysqli(‘localhost’, ‘zzzz’)必须使用完全限定名称\className(),防止拼接当前命名空间。

一点小细节:定义命名空间的前面,别写其他代码。
命名空间可以像文件路径一样细化为多层子命名空间,把1.php的命名空间修改为NP\np_01,把2.php的命名空间修改为NP\np_02,把3.php并设置其命名空间为NP


使用use关键字引入命名空间,访问命名空间下的不同内容,修饰关键字也不同,类是use 命名空间\类型,函数是use function 命名空间\函数名,常量是use const 命名空间\常量名 AS关键字设置别名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//1. 不使用use关键字
/*
require_once '1.php';
\NP\np_01\testMethod();
*/

// 2.使用use关键字
/*
namespace NP\np_04;
use function NP\np_01\testMethod; // 不使用AS别名,则以最后部分为别名
require_once '1.php';
testMethod();
*/

// 3.use + AS 别名
/*
namespace NP\np_04;
use function NP\np_01\testMethod AS zwk;
require_once '1.php';
zwk();
*/



一篇比较好的PHP命名空间与自动加载机制介绍的文章

显示 Gitment 评论