@@ -36,9 +36,12 @@ namespace com\aa{
3636namespace com\bb;
3737/* ... */
3838``` 
39+ 如果没有定义任何命名空间,所有的类、函数和常量的定义都是在全局空间,与 PHP 引入命名空间概念前一样。
40+ 
3941### 8.2.2 内部实现  
4042命名空间的实现实际比较简单,当声明了一个命名空间后,接下来编译类、函数和常量时会把类名、函数名和常量名统一加上命名空间的名称作为前缀存储,也就是说声明在命名空间中的类、函数和常量的实际名称是被修改过的,这样来看他们与普通的定义方式是没有区别的,只是这个前缀是内核帮我们自动添加的,例如:
4143``` php 
44+ //ns_define.php
4245namespace com\aa;
4346
4447const MY_CONST = 1234;
@@ -169,3 +172,102 @@ __(2)编译常量__
169172总结下命名空间的定义:编译时如果发现定义了一个namespace,则将命名空间名称保存到FC(current_namespace),编译类、函数、常量时先判断FC(current_namespace)是否为空,如果为空则按正常名称编译,如果不为空则将类名、函数名、常量名加上FC(current_namespace)作为前缀,然后再以修改后的名称注册。整个过程相当于PHP帮我们补全了类名、函数名、常量名。 
170173
171174## 8.3 使用命名空间 
175+ ### 8.3.1 基本使用 
176+ 上一节我们知道了定义在命名空间中的类、函数和常量只是加上了namespace名称作为前缀,既然是这样那么在使用时加上同样的前缀是否就可以了呢?答案是肯定的,比如上面那个例子:在com\aa命名空间下定义了一个常量MY_CONST,那么就可以这么使用: 
177+ ```php 
178+ include 'ns_define.php'; 
179+ 
180+ echo \com\aa\MY_CONST; 
181+ ``` 
182+ 这种按照实际类名、函数名、常量名使用的方式很容易理解,与普通的类型没有差别,这种以"\" 开头使用的名称称之为:完全限定名称,类似于绝对目录的概念,使用这种名称PHP会直接根据"\" 之后的名称去对应的符号表中查找(namespace定义时前面是没有加"\" 的,所以查找时也会去掉这个字符)。
183+ 
184+ 除了这种形式的名称之外,还有两种形式的名称:
185+ *  __ 非限定名称:__  即没有加任何namespace前缀的普通名称,比如my_func(),使用这种名称时如果当前有命名空间则会被解析为:currentnamespace\my_func,如果当前没有命名空间则按照原始名称my_func解析
186+ *  __ 部分限定名称:__  即包含namespace前缀,但不是以"\" 开始的,比如:aa\my_func(),类似相对路径的概念,这种名称解析规则比较复杂,如果当前空间没有使用use导入任何namespace那么与非限定名称的解析规则相同,即如果当前有命名空间则会把解析为:currentnamespace\aa\my_func,否则解析为aa\my_func,使用use的情况后面再作说明
187+ 
188+ ### 8.3.2 use导入  
189+ 使用一个命名空间中的类、函数、常量虽然可以通过完全限定名称的形式访问,但是这种方式需要在每一处使用的地方都加上完整的namespace名称,如果将来namespace名称变更了就需要所有使用的地方都改一遍,这将是很痛苦的一件事,为此,PHP提供了一种命名空间导入/别名的机制,可以通过use关键字将一个命名空间导入或者定义一个别名,然后在使用时就可以通过导入的namespace名称最后一个域或者别名访问,不需要使用完整的名称,比如:
190+ ``` php 
191+ //ns_define.php
192+ namespace aa\bb\cc\dd;
193+ 
194+ const MY_CONST = 1234;
195+ ``` 
196+ 可以采用如下几种方式使用:
197+ ``` php 
198+ //方式1:
199+ include 'ns_define.php';
200+ 
201+ use aa\bb\cc\dd;
202+ 
203+ echo dd\MY_CONST;
204+ ``` 
205+ ``` php 
206+ //方式2:
207+ include 'ns_define.php';
208+ 
209+ use aa\bb\cc;
210+ 
211+ echo cc\dd\MY_CONST;
212+ ``` 
213+ ``` php 
214+ //方式3:
215+ include 'ns_define.php';
216+ 
217+ use aa\bb\cc\dd as DD;
218+ 
219+ echo DD\MY_CONST;
220+ ``` 
221+ ``` php 
222+ //方式4:
223+ include 'ns_define.php';
224+ 
225+ use aa\bb\cc as CC;
226+ 
227+ echo CC\dd\MY_CONST;
228+ ``` 
229+ 这种机制的实现原理也比较简单:编译期间如果发现use语句 ,那么就将把这个use后的命名空间名称插入一个哈希表:FC(imports),而哈希表的key就是定义的别名,如果没有定义别名则key使用按"\" 分割的最后一节,比如方式2的情况将以cc作为key,即:FC(imports)[ "cc"]  = "aa\bb\cc\dd";接下来在使用类、函数和常量时会把名称按"\" 分割,然后以第一节为key查找FC(imports),如果找到了则将FC(imports)中保存的名称与使用时的名称拼接在一起,组成完整的名称。实际上这种机制是把完整的名称切割缩短然后缓存下来,使用时再拼接成完整的名称,也就是内核帮我们组装了名称,对内核而言,最终使用的都是包括完整namespace的名称。
230+ 
231+ ![ ] ( ../img/namespace_com.png ) 
232+ 
233+ use除了上面介绍的用法外还可以导入一个类,导入后再使用类就不需要加namespace了,例如:
234+ ``` php 
235+ //ns_define.php
236+ namespace aa\bb\cc\dd;
237+ 
238+ class my_class { /* ... */ }
239+ ``` 
240+ ``` php 
241+ include 'ns_define.php';
242+ //导入一个类
243+ use aa\bb\cc\dd\my_class;
244+ //直接使用
245+ $obj = new my_class();
246+ var_dump($obj);
247+ ``` 
248+ use的这两种用法实现原理是一样的,都是在编译时通过查找FC(imports)实现的名称补全。从PHP 5.6起,use又提供了两种针对函数、常量的导入,可以通过` use function xxx ` 及` use const xxx ` 导入一个函数、常量,这种用法的实现原理与上面介绍的实际是相同,只是在编译时没有保存到FC(imports),zend_file_context结构中的另外两个哈希表就是在这种情况下使用的:
249+ ``` c 
250+ typedef  struct  _zend_file_context {
251+  ... 
252+  //用于保存导入的类或命名空间 
253+  HashTable *imports; 
254+  //用于保存导入的函数 
255+  HashTable *imports_function; 
256+  //用于保存导入的常量 
257+  HashTable *imports_const; 
258+ } zend_file_context;
259+ ``` 
260+ 简单总结下use的几种不同用法:
261+ *  __ a.导入命名空间:__  导入的名称保存在FC(imports)中,编译使用的语句时搜索此符号表进行补全
262+ *  __ b.导入类:__  导入的名称保存在FC(imports)中,与a不同的时如果不会根据"\" 切割后的最后一节检索,而是直接使用类名查找
263+ *  __ c.导入函数:__  通过` use function ` 导入到FC(imports_function),补全时先查找FC(imports_function),如果没有找到则继续按照a的情况处理
264+ *  __ d.导入常量:__  通过` use const ` 导入到FC(imports_const),不全是先查找FC(imports_const),如果没有找到则继续按照a的情况处理
265+ 
266+ 比如:
267+ ``` php 
268+ use aa\bb; //导入namespace
269+ use aa\bb\MY_CLASS; //导入类
270+ use function aa\bb\my_func; //导入函数
271+ use const aa\bb\MY_CONST; //导入常量
272+ ``` 
273+ 
0 commit comments