目录启示:PHP 中 命名空间及其成员的访问

文章目录

参考

项目 描述
搜索引擎 BingGoogle
AI 大模型 文心一言通义千问讯飞星火认知大模型ChatGPT
PHP 官方 PHP Manual
PHP 官方 language.namespaces.rationale.php

环境

项目 描述
PHP 5.5.05.6.87.0.07.2.57.4.98.0.08.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) 系统中的绝对路径、相对路径相对应。具体如下:

  1. 完全限定名称
    完全限定名称表明了从全局命名空间到目标命名空间所经历的一系列命名空间,如 \HOME\RedHeart\BinaryMoon 就是一个完全限定名称。完全限定名称可与 类 Unix 系统中的绝对路径进行类比。
  2. 限定名称
    限定名称表明了从当前命名空间到目标命名空间所经历的一系列命名空间,如在 \HOME 命名空间中使用的 RedHeart\BinaryMoon 就是一个限定名称,其完全限定名称为 \HOME\RedHeart\BinaryMoon。限定名称可与 类 Unix 系统中的相对路径进行类比。
  3. 非限定名称
    非限定名称仅仅使用单个命名空间名称表示需要访问的命名空间,如在 \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
相关推荐
柒星栈14 分钟前
PHP 源码怎么加密防破解?三套方案实战指南
开发语言·php·android studio
小小代码狗27 分钟前
SQLi-Labs 基础注入实战教程(Less-1 ~ Less-5and Less-9)
服务器·python·php
shencz20002 小时前
在windows10里的apache2.4加php7.2的环境下上安装Laravel5.8框架
php·laravel
TlSfoward20 小时前
抓包代理链路下的 TLS 指纹变化分析 TLSFOWARD抓包工具
数据库·爬虫·网络协议·搜索引擎·php
—Miss. Z—1 天前
计算机二级MySQL——简单应用题(存储过程&存储函数)
数据库·oracle·php
故乡de云1 天前
AWS 添加付款方式失败排查清单:卡片、银行风控与账号状态逐项定位
开发语言·php
梦梦代码精1 天前
基于ThinkPHP6 + Vue3的家政预约系统全解析:从LBS定位到自动派单的完整实现
java·docker·开源·php·代码规范
郑州光合科技余经理1 天前
家政O2O平台解析:从0搭建上门预约小程序解决方案
android·java·开发语言·前端·小程序·架构·php
lxw18449125141 天前
PHP后端(CI框架方向)面试题库,分为基础必问、MySQL、Redis、工程运维、高阶加分、场景实操六大模块,适配该JD全部考点,附带标准答案
ci/cd·面试·php
郑州光合科技余经理1 天前
家政预约小程序后端源码深度剖析:支付回调实战
java·开发语言·前端·git·小程序·架构·php