![PHP面试一战到底](https://wfqqreader-1252317822.image.myqcloud.com/cover/891/44509891/b_44509891.jpg)
5.3 命名空间
命名空间是对类的层级结构的一种封装方式,类似于操作系统的目录。在不同的命名空间下,用户不用担心类/函数/常量的名字冲突,在引入第三方类库时,也不用担心名字冲突。
在引入其他命名空间之下的类库时,如果标识符名称冲突或过长,可以使用use as来创建别名。
5.3.1 命名空间的使用规范
1.命名空间的定义
使用namespace来定义命名空间。定义命名空间的规则非常宽松,即“命名空间的定义必须放在程序里的第一条语句”。参考以下示例:(源码文件:ch05/basic/phpbook.php)
![](https://epubservercos.yuewen.com/9146EB/23721566801954006/epubprivate/OEBPS/Images/Figure-P84_41128.jpg?sign=1738930921-DuZ1TePYkjjdIh7fkamWGKRXEZRU7Q6K-0-e9b3e2f097649b58cd42b2b7150e3c4b)
2.使用命名空间
使用命名空间的关键字为use,PHP支持三种使用方式:
(1)使用类use class
use PHPBook\Demo;//使用命名空间之下的类
(2)使用函数use function
use function PHPBook\say_hello;//使用命名空间之下的函数
(3)使用常量use const
use const PHPBook\HELLO_STRING;//使用命名空间之下的常量
具体程序示例如下:(源码文件:ch05/basic/test_namespace.php)
<?php include './phpbook.php'; use function PHPBook\say_hello;//使用命名空间之下的函数 use const PHPBook\HELLO_STRING;//使用命名空间之下的常量 use PHPBook\Demo;//使用命名空间之下的类 say_hello(); //output:Hello World echo HELLO_STRING; //output:Hello World $demo = new Demo(); $demo->say_hello(); //output:Hello World
3.别名关键字as
在引入其他命名空间之下类库时,如果标识符名称冲突或过长,可以使用use as来创建别名。
use PHPBook\Demo as Demo;//使用命名空间之下的类 use function PHPBook\say_hello as say_hello;//使用命名空间之下的函数 use const PHPBook\HELLO_STRING as HELLO_STRING;//使用命名空间之下的常量
4.类的解析规则
如果使用中引入了多个命名空间下的名称相同的类,那么PHP解析时如何知道引用的哪个类呢?要回答这个问题,需要知道类的解析规则:
● 规则1:类名无前缀,则解析后完整类目为“当前命名空间+类名”。
● 规则2:类名有前缀,则解析后完整类目为“当前命名空间+子命名空间+类名”。
● 规则3:类名以全局前缀\开始,为完整路径,无须解析。
为了解释这些规则,我们来看代码文件ch05/prefix下的示例,文件目录结构如下:
./test_prefix.php ./foo/demo.php ./foo/bar/demo.php
其中./foo/demo.php定义了Demo类:
(源码文件:ch05/prefix/foo/demo.php)
![](https://epubservercos.yuewen.com/9146EB/23721566801954006/epubprivate/OEBPS/Images/Figure-P85_41127.jpg?sign=1738930921-ICtgjctkJ52MFlBV3LGoFFvQgHsy8GJ7-0-1ddb34992f0f79156456d2cc120da169)
./foo/bar/demo.php的定义与./foo/demo.php类似,只有命名空间不同,不再赘述:
namespace PHPBook\Foo\Bar;
./test_prefix.php的第6至10行也定义了一个名称为Demo的类,以下程序代码演示如何使用3个相同的类。
(源码文件:ch05/prefix/test_prefix.php)
![](https://epubservercos.yuewen.com/9146EB/23721566801954006/epubprivate/OEBPS/Images/Figure-P86_41118.jpg?sign=1738930921-crj4VSjIG0jQRBCvn9PybNezAVvbkJvC-0-45e51f6d61f2a9292d1bb23026be64e4)
第12行直接不加任何前缀的使用了Demo类,此时适用规则1,最终引用的类名为“当前命名空间+类名”。
第16行,前缀(或称为子命名空间)为Foo,适用规则2,最终引用的类名为“当前命名空间+子命名空间+类名”。
第20行,类名以全局前缀\开始,为完整路径,适用规则3,无须解析。
5.全局命名空间
由于命名空间是PHP 5.3版本引入的特性,在此之前,PHP已经有大量的类和函数。为了向下兼容,这些无命名空间的类,默认为全局命名空间,使用时需要加上前缀\。例如在其他命名空间下,$class = new StdClass()需要更改为$class = new \StdClass()。
6.命名空间最佳实践
遵守PSR-0和PSR-4标准。
PHP并没有规定命名空间与文件的对应关系,例如在文件foo\a.php里定义类\FOO\BAR是可以的。但不推荐这么做。一般而言,\FOO\BAR对应的文件应为foo\bar.php。PSR标准将在下节进行详细讲述。
● 一个文件只包含一个命名空间。
PHP支持同一个文件里定义多个命名空间,但强烈不建议,因为这样会使程序的可读性变差。
● 一个use只使用一个命名空间。
PHP支持一个use使用多个命名空间,例如:
![](https://epubservercos.yuewen.com/9146EB/23721566801954006/epubprivate/OEBPS/Images/Figure-P87_41116.jpg?sign=1738930921-SWhU32GqHZIa69F9Wke73vxAsbnVICeU-0-7a48e414926a6abe928e07bf3e71ae7f)
但不建议如此使用,因为增加、删除、更改use语句时容易出错。
5.3.2 面试题:命名空间
题目描述:命名空间是什么,为什么需要命名空间?
答案见本节开头部分的讲解,读者需要闭卷回答以上问题。
5.3.3 面试题:类名冲突的解决方法
题目描述:一个项目中有多个相同的类,如何使用才能避免冲突。
解答:参考类的解析规则,读者需要了解三种规则及其适用条件。