PHP面试一战到底
上QQ阅读APP看书,第一时间看更新

5.3 命名空间

命名空间是对类的层级结构的一种封装方式,类似于操作系统的目录。在不同的命名空间下,用户不用担心类/函数/常量的名字冲突,在引入第三方类库时,也不用担心名字冲突。

在引入其他命名空间之下的类库时,如果标识符名称冲突或过长,可以使用use as来创建别名。

5.3.1 命名空间的使用规范

1.命名空间的定义

使用namespace来定义命名空间。定义命名空间的规则非常宽松,即“命名空间的定义必须放在程序里的第一条语句”。参考以下示例:(源码文件:ch05/basic/phpbook.php)

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)

./foo/bar/demo.php的定义与./foo/demo.php类似,只有命名空间不同,不再赘述:

namespace PHPBook\Foo\Bar;

./test_prefix.php的第6至10行也定义了一个名称为Demo的类,以下程序代码演示如何使用3个相同的类。

(源码文件:ch05/prefix/test_prefix.php)

第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使用多个命名空间,例如:

但不建议如此使用,因为增加、删除、更改use语句时容易出错。

5.3.2 面试题:命名空间

题目描述:命名空间是什么,为什么需要命名空间?

答案见本节开头部分的讲解,读者需要闭卷回答以上问题。

5.3.3 面试题:类名冲突的解决方法

题目描述:一个项目中有多个相同的类,如何使用才能避免冲突。

解答:参考类的解析规则,读者需要了解三种规则及其适用条件。