PHP 5.5类名解析

9

PHP 5.5实现了一个新特性,可以通过语法::class来检索类名:

<?php

namespace Testing;

class Test{}

echo Test::class; // Testing\Test;

这段代码能够完美运行,没问题吧?但是我和一些朋友想知道的是,当使用未声明的类名时,为什么这种语法也会返回一个类名。例如:

<?php

echo UndeclaredClass::class; // UndeclaredClass

在其他几种情况下会出现错误,但这里没有。有人知道为什么会发生这种情况吗?最好能给出具体的依据。

这是否与后期静态绑定有关,还是这个全新功能的(暂时)限制/缺陷呢?


有趣的问题。为什么不在PHP开发者邮件列表上询问(或参考此页面)? - Borislav Sabev
如果我说我不知道怎么做,你会相信我吗? - user753531
好的,既然我知道这有多么复杂:http://bg2.php.net/contact.phphttp://bg2.php.net/support.php你最好、最快的选择是邮件列表,因为没有官方IRC频道。请在此处分享答案。 - Borislav Sabev
这对我来说无法重现,<?php echo UndeclaredClass::class; 总是会抛出错误。 - Daniel W.
2个回答

5

终于有了官方答案……相对来说。今天我在一个 错误报告 中得到了一个人(他的邮箱是 requinix@php.net)的回答。唯一的例外是这个人与 PHP 开发的联系。

简而言之

PHP 不需要知道类的定义就能获取其完整名称。所有必需的信息都在编译时可用,因此不需要加载它。

详细解释

命名空间就像use一样,在编译时被解析,也就是文件在执行前编译。这就是为什么使用它们有严格要求的原因。

由于所有这些要求,当 PHP 遇到一个类名时,它可以立即知道它的完整名称。把它想象成一个文件系统,命名空间就像相对位置下的一个目录,而use则是符号链接。

类名可以是绝对的(" \Testing\Test "),也可以是相对的("Test"),如果是相对的话,就可能是正常的名称。 [需要更多上下文]

namespace Testing {
    echo Test::class; // \Testing + Test = \Testing\Test
}

或者是一个“别名”:
use Testing\Test as AliasedTest;
echo AliasedTest::class; // AliasedTest + use = \Testing\Test

如果没有所有这些的话,自动加载就无法工作!

::class只是一个公开展示PHP一直以来已知信息的新工具。

这个“扩展回答”基本上和我收到的错误报告一样。为什么有这么多明显的复制和粘贴呢?最初,我为另一个Stack Overflow社区构建了这个答案。


你能解释一下为什么 echo UndeclaredClass::class; 对你来说不会抛出错误吗? - Daniel W.
1
回答我的支持票的人向我解释说,在实例化对象之前获取类名,因此不会引发错误,因为不需要加载类。 - user753531
1
这实际上非常有用——它允许IDE在设计时捕捉拼写错误,而不会在运行时产生潜在的开销(比如与IOC容器惰性注册相关)。感谢您提供正式声明。 - Steve

0

您可以使用get_class函数获取带有命名空间的类名。这是一个很好的方法。 以下是您可以尝试此代码的代码:

<?php
namespace Testing;

class Test{
    public function abc()
    {
        echo "This is the ABC.";
    }
}

namespace Testing1;

class Test{
    public function abc()
    {
        echo "This is the ABC.";
    }
}
// echo Test::class; // Testing\Test;
$test =  new Test();

print_r(get_class($test));
// echo "<br>";
// echo UndeclaredClass::class;
?>

虽然我很感谢你的回答,但那不是问题的重点。我并不是在尝试检索类名。相反,我试图理解为什么这样的功能没有引发错误。 - user753531

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接