文章目录
- 参考
- 环境
- 三种名称
- 非限定名称
- 限定名称
- 完全限定名称
- 举个栗子
- use
- use 关键字
- use ... as ..
- 命名冲突
- 真假美猴王
- 两个世界
参考
项目 | 描述 |
---|---|
搜索引擎 | 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 命名空间的上下文中,限定名称 (Qualified Name)、非限定名称 (Unqualified Name) 与完全限定名称 (Fully Qualified Name) 是 三种引用命名空间中的元素(类、接口、函数 与 常量)的方式
。
非限定名称
非限定名称是一个 不包含任何命名空间前缀的名称
,如 ClassName
就是一个非限定名称。当使用非限定名称时,PHP 会 优先在当前命名空间中查找该元素
。若该原始不存在于当前命名空间中,则将在全局命名空间中对其进行查找(仅当被查找元素为函数或常量时)
。
限定名称
限定名称包含 命名空间前缀,但没有开头的反斜线 \(该反斜线表示全局命名空间)
。如 NamespaceName\ClassName
与 NamespaceName\functionName()
就是限定名称。当使用限定名称时,PHP 会 基于当前命名空间来解析该名称
。
完全限定名称
完全限定名称从反斜线 \(该反斜线表示全局命名空间)
开始,后接命名空间或元素的名称。如 \Full\NamespaceName\ClassName
与 \Full\NamespaceName\functionName()
就是完全限定名称。当使用完全限定名称时,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());
}
执行效果
string(24) "HOME\RedHeart\BinaryMoon"
string(13) "HOME\RedHeart"
string(24) "HOME\RedHeart\BinaryMoon"
use
use 关键字
在 PHP 中,use
关键字用于导入命名空间中的 类
、接口
、函数
或 常量
,以便在当前命名空间中直接使用这些元素的 非限定名称
,有助于提高开发体验😎。对此,请参考如下示例:
<?php
namespace HOME\RedHeart\BinaryMoon {
const CONSTANT = __NAMESPACE__;
class MyClass
{
public $name = 'RedHeart';
public $nation = 'China';
public $age = 18;
}
function sayHello() {
print("Hello World\n");
}
}
namespace {
# 将 \HOME\RedHeart\BinaryMoon\ 命名空间下的
# MyClass 类导入至当前命名空间,便可以使用非限定名称访问该类。
use \HOME\RedHeart\BinaryMoon\MyClass;
var_dump(new MyClass());
# 将 \HOME\RedHeart\BinaryMoon\ 命名空间下的
# 函数 sayHello 与常量 CONSTANT 导入当前命名空间
use function HOME\RedHeart\BinaryMoon\sayHello;
use const HOME\RedHeart\BinaryMoon\CONSTANT;
sayHello();
print(CONSTANT . "\n");
}
执行效果
在 PHP 中,use
关键字的默认操作对象是 类
。若您需要将 函数
或 常量
导入至当前命名空间,请在 use
关键字后添加 function
或 const
以告知 PHP 解释器。
object(HOME\RedHeart\BinaryMoon\MyClass)#1 (3) {
["name"]=>
string(8) "RedHeart"
["nation"]=>
string(5) "China"
["age"]=>
int(18)
}
Hello World
HOME\RedHeart\BinaryMoon
use … as …
在 PHP 中,use ... as ...
语句用于导入命名空间中的 类
、接口
、函数
或 常量
并为它们创建一个 别名
,以便可以在当前代码块中使用别名来引用相关的元素。对此,请参考如下示例:
<?php
namespace HOME\RedHeart\BinaryMoon {
const CONSTANT = __NAMESPACE__;
class MyClass
{
public $name = 'RedHeart';
public $nation = 'China';
public $age = 18;
}
function sayHello() {
print("Hello World\n");
}
}
namespace {
use \HOME\RedHeart\BinaryMoon\MyClass as AnClass;
use function HOME\RedHeart\BinaryMoon\sayHello as speakHello;
use const HOME\RedHeart\BinaryMoon\CONSTANT as ANCONSTANT;
var_dump(new AnClass());
speakHello();
print(ANCONSTANT . "\n");
}
执行效果
object(HOME\RedHeart\BinaryMoon\MyClass)#1 (3) {
["name"]=>
string(8) "RedHeart"
["nation"]=>
string(5) "China"
["age"]=>
int(18)
}
Hello World
HOME\RedHeart\BinaryMoon
命名冲突
真假美猴王
<?php
namespace BinaryMoon {
class BinaryMoon {}
}
在上述示例中,命名空间 BinaryMoon
与其 类元素 BinaryMoon
使用相同名称。按照正常情况,两者将发生 命名冲突
,但上述示例却能够正常执行。这是由于,命名空间 BinaryMoon
的完全限定名称是 \BinaryMoon
,而 类元素 BinaryMoon
的完全限定名称是 \BinaryMoon\BinaryMoon
,两者的名称 并不真的相同
。
两个世界
实际上,命名空间与其他元素之间并不会产生命名冲突,即使两者的完全限定名称一模一样
。对此,请参考如下示例:
<?php
namespace BinaryMoon {}
namespace {
class BinaryMoon {}
var_dump(new \BinaryMoon());
}
执行效果
在使用 class 关键字创建类 BinaryMoon 后,类与命名空间具有相同的完全限定名称 \BinaryMoon
,这并不会导致两者发生 命名冲突
,PHP 会 依据具体情景进行分析来确定如何解析该名称
。但程序并非完美的,它无法应对所有可能的场景,鉴于此,请 尽可能不要尝试使用相同的名称
。
object(BinaryMoon)#1 (0) {
}