文章目录
- 参考
- 环境
- 命名空间的使用
- [namespace 关键字](#namespace 关键字)
-
-
- [namespace 的两大功能](#namespace 的两大功能)
- [使用 namespace\ 访问当前命名空间下的元素](#使用 namespace\ 访问当前命名空间下的元素)
-
- 未雨绸缪
- (完全)限定名称下的未定义常量
-
-
- [PHP8 以下](#PHP8 以下)
- [PHP8 及以上](#PHP8 及以上)
- 任何情况下的(完全)限定名称下的未定义常量
-
参考
项目 | 描述 |
---|---|
搜索引擎 | Bing 、Google |
AI 大模型 | 文心一言 、通义千问 、讯飞星火认知大模型 、ChatGPT |
PHP 官方 | PHP Manual |
PHP 官方 | language.namespaces.rationale.php |
环境
项目 | 描述 |
---|---|
PHP | 5.5.0 、5.6.8 、7.0.0 、7.2.5 、7.4.9 、8.0.0 、8.2.9 |
PHP 编辑器 | PhpStorm 2023.1.1(专业版) |
命名空间的使用
全局命名空间成员
全局命名空间成员是指位于 PHP 全局命名空间下的 类
、接口
、函数
和 常量
。全局命名空间是 PHP 脚本的默认命名空间,也被称为 根命名空间
。
php
<?php
# 定义全局命名空间成员 MyClass、CONSTANT 以及 func。
class MyClass {}
const CONSTANT = "";
function func() {}
在上述示例中,我们定义了全局命名空间成员 \MyClass
、\CONSTANT
以及 \func
。其中,\
指代全局命名空间。在全局命名空间中访问全局命名空间成员可以不添加 \
前缀,但在其他命名空间中对全局命名空间成员进行访问则 推荐使用前缀
,否则很可能将 使用当前命名空间下的同名成
员。对此,请参考如下示例:
php
<?php
# 全局命名空间
namespace {
const HOME = 'BinaryMoon';
}
# 命名空间 \RedHeart
namespace RedHeart {
const HOME = 'China';
# 尝试访问常量 HOME
var_dump(HOME);
var_dump(\HOME);
}
执行效果
php
string(5) "China"
string(10) "BinaryMoon"
HOME
在命名空间 RedHeart
中的 完全限定名称(可以将其理解为绝对路径)
为 \RedHeart\HOME
,在使用 类
、接口
、函数
和 常量
这些受命名空间影响的组份时,若没有对名称进行 限定(可以理解为相对路径中的一种,相对当前目录进行文件的访问)
,则将视该名称为当前命名空间成员所属。
由于 HOME
属于未限定名称,故其被解析为 \RedHeart\HOME
,而 \HOME
属于完全限定名称,故将使用全局命名空间下的 HOME
常量。
子命名空间成员
在 声明命名空间时
,命名空间所使用的名称均是相对于全局命名空间进行命名的。而在 访问命名空间成员时
,则存在三种名称,这三种名称分别可与 类 Unix(如 Linux)
系统中的绝对路径、相对路径相对应。具体如下:
- 完全限定名称
完全限定名称表明了从全局命名空间到目标命名空间所经历的一系列命名空间,如\HOME\RedHeart\BinaryMoon
就是一个完全限定名称。完全限定名称可与 类 Unix 系统中的绝对路径进行类比。 - 限定名称
限定名称表明了从当前命名空间到目标命名空间所经历的一系列命名空间,如在\HOME
命名空间中使用的RedHeart\BinaryMoon
就是一个限定名称,其完全限定名称为\HOME\RedHeart\BinaryMoon
。限定名称可与 类 Unix 系统中的相对路径进行类比。 - 非限定名称
非限定名称仅仅使用单个命名空间名称表示需要访问的命名空间,如在\HOME
命名空间中使用的RedHeart
就是一个非限定名称,其完全限定名称为\HOME\RedHeart
。非限定名称同样可与 类 Unix 系统中的相对路径进行类比。
php
<?php
namespace HOME\RedHeart {
function saySelf() {
# 通过魔术常量 __NAMESPACE 回当前所属的命名空间名称
return __NAMESPACE__;
}
function saySon() {
# 尝试访问当前命名空间中的子命名空间 BinaryMoon 中的 saySelf() 函数
return BinaryMoon\saySelf();
}
}
namespace HOME\RedHeart\BinaryMoon {
function saySelf() {
return __NAMESPACE__;
}
}
# 全局命名空间
namespace {
# 尝试访问 HOME\RedHeart\BinaryMoon 命名空间下的 saySelf() 函数
var_dump(\HOME\RedHeart\BinaryMoon\saySelf());
# 尝试访问 HOME\RedHeart 命名空间下的 saySelf() 函数
var_dump(HOME\RedHeart\saySelf());
# 尝试访问 HOME\RedHeart 命名空间下的 saySon() 函数
var_dump(\HOME\RedHeart\saySon());
}
执行效果
php
string(24) "HOME\RedHeart\BinaryMoon"
string(13) "HOME\RedHeart"
string(24) "HOME\RedHeart\BinaryMoon"
namespace 关键字
namespace 的两大功能
在 PHP 中,namespace 关键字常用于 命名空间的声明
与 当前命名空间下元素的访问
。
使用 namespace\ 访问当前命名空间下的元素
在使用 namespace 访问当前命名空间元素时,namespace 后需要紧跟反斜线 \
,后跟子命名空间或 其他元素(类、接口、函数 和 常量)
。对此请参考如下示例:
php
<?php
namespace HOME\RedHeart {
const CONSTANT = __NAMESPACE__;
function func() {}
class MyClass {}
}
namespace HOME\RedHeart\BinaryMoon {
const CONSTANT = __NAMESPACE__;
function func() {}
class MyClass {}
}
namespace HOME\RedHeart {
# 访问当前命名空间下除子命名空间外的其他元素
var_dump(namespace\CONSTANT);
new namespace\MyClass();
namespace\func();
# 访问当前命名空间的子命名空间 BinaryMoon 内的元素
var_dump(namespace\BinaryMoon\CONSTANT);
new namespace\BinaryMoon\MyClass();
namespace\BinaryMoon\func();
}
执行结果
php
string(13) "HOME\RedHeart"
string(24) "HOME\RedHeart\BinaryMoon"
未雨绸缪
第一深情
在使用非限定名称对元素进行访问时
,类名称 总是基于当前命名空间进行解析
。因此 在其他命名空间中尝试访问全局命名空间中的类时,必须使用完全限定名称
。对此,请参考如下示例:
php
<?php
namespace {
# 在全局命名空间中定义类 MyClass
class MyClass {}
}
namespace HOME {
# 在 \HOME 全局命名空间中尝试
# 使用非限定名称对 \MyClass 类进行访问
$myClass = new MyClass();
}
执行效果
即使在 当前命名空间中(非全局命名空间)
未找到名为 MyClass
的类,PHP 也 不会尝试将其解析为全局命名空间中的元素
。
php
PHP Fatal error: Uncaught Error: Class 'HOME\MyClass' not found in C:\test.php:12
Stack trace:
#0 {main}
thrown in C:\test.php on line 12
向上突围
函数与常量的名称与类名称的解析存在差异。在使用非限定名称对元素进行访问时
,如果当前命名空间中不存在该函数或常量,PHP 会 退而使用全局空间中的函数或常量
。对此,请参考如下示例:
php
<?php
namespace {
# 在全局命名空间中定义函数 sayHello 与 常量 CONSTANT
function sayHello() {
print('Hello World' . "\n");
}
const CONSTANT = __NAMESPACE__;
}
namespace HOME {
# 在 \HOME 命名空间中,
# 尝试使用非限定名称对元素进行访问。
sayHello();
var_dump(CONSTANT);
}
执行效果
php
Hello World
string(0) ""
(完全)限定名称下的未定义常量
PHP8 以下
在 PHP8 以下版本中,尝试访问未定义常量将导致 Warning
异常,该常量的名称的字符串形式将作为访问结果
。对此,请参考如下示例:
php
<?php
# 尝试访问未定义常量
var_dump(CONSTANT);
执行效果
在 PHP7.2.5
中执行上述代码,得到如下结果:
php
PHP Warning: Use of undefined constant CONSTANT - assumed 'CONSTANT' (this will throw an Error in a future version of PHP) in C:\test.php on line 5
string(8) "CONSTANT"
PHP8 及以上
在 PHP8 及以上版本中,尝试访问未定义常量将导致 Fatal
异常,PHP 将因此立即终止程序。对此,请参考如下示例:
php
<?php
# 尝试访问未定义常量
var_dump(CONSTANT);
执行效果
在 PHP8.0.0
中执行上述代码,得到如下结果:
php
PHP Fatal error: Uncaught Error: Undefined constant "CONSTANT" in C:\test.php:5
Stack trace:
#0 {main}
thrown in C:\test.php on line 5
任何情况下的(完全)限定名称下的未定义常量
在任何 PHP 版本中,使用完全限定名称或限定名称对未定义常量进行访问都将导致 Fatal
异常,PHP 程序都将为此立即终止。对此,请参考如下示例:
php
<?php
# 尝试访问未定义常量
namespace HOME\RedHeart {
}
namespace HOME {
# 尝试通过完全限定名称对未定义常量进行访问
var_dump(\HOME\RedHeart\CONSTANT);
}
php
<?php
# 尝试访问未定义常量
namespace HOME\RedHeart {
}
namespace HOME {
# 尝试通过限定名称对未定义常量进行访问
var_dump(RedHeart\CONSTANT);
}
执行效果
在 PHP7.2.5
中,执行上述两组示例都将得到如下类似结果:
php
PHP Fatal error: Uncaught Error: Undefined constant 'HOME\RedHeart\CONSTANT' in C:\test.php:10
Stack trace:
#0 {main}
thrown in C:\test.php on line 10