命名空间的 PHP 使用语句

Posted

技术标签:

【中文标题】命名空间的 PHP 使用语句【英文标题】:PHP use statement for namespace 【发布时间】:2014-10-29 16:41:50 【问题描述】:

也许这是一个奇怪的问题,但我无法弄清楚当您编写时 php 内部发生了什么:

use garcha\path\class;

我不是在问命名空间的用途,而是关于该语句本身,即使它没有分配任何内存,我的意思是,当你甚至为某个类提供别名时:

use garcha\path\class as withNewName;

它存储在哪里?或者它是如何记住名字的?它只是在编译时发生吗?而不是运行时间?就像只是描述函数一样。

【问题讨论】:

如果您熟悉 C,请查看实现:lxr.php.net/xref/PHP_TRUNK/Zend/zend_compile.c#zend_compile_use。它通过将名称存储在哈希表中来记住它们(另请参见 zend_get_import_ht)。是的,别名解析是完全编译时的。 VM 不知道命名空间别名。 您可以通过制作像namespace Test class MyClass namespace use Test\MyClass; 这样的简单脚本然后使用phpdbg 转储操作码来亲眼看到这是编译时间。您只会得到 ZEND_NOP,因为那里没有运行时代码。 lxr 已关闭(2017 年 5 月)。使用 github github.com/php/php-src/blob/master/Zend/zend_compile.c#L6408 或启动 docker 容器 hub.docker.com/r/itszero/opengrok 【参考方案1】:

这不是一个非常复杂的算法(对于 5.5,在 5.6 中描述的类名部分是相同的)。

    如有必要,将创建 HashTable 实例。它保持导入(使用的命名空间类)。 在使用as 关键字的情况下,此名称用作别名。否则使用导入类名的最后一个组件(对于 XXX\YYY\ZZZ,名称将是 ZZZ)。将其转换为小写。 检查self/parent,它不能用作别名。 检查该名称是否已存在于 class_table 中(使用当前命名空间,如果已声明)。 将此别名添加到特殊的 HashTable(第 1 页中提到)。

这个表用在什么地方?

就在编译期间解析类名。

关于别名还有一件更有趣的事情——它的作用域是命名空间块:

<?php

namespace nsC

    class classC 


namespace nsA

    use nsC\classC as importC;
    new importC();


namespace nsB

    // ERROR!
    new importC(); // or \nsA\importC()

【讨论】:

以上是关于命名空间的 PHP 使用语句的主要内容,如果未能解决你的问题,请参考以下文章

命名空间

PHP 命名空间和“使用”

命名空间

PHP面向对象 – 命名空间

关于命名空间namespace

命名空间