在动态评估命名空间元素时,为什么必须使用完全限定的名称? [英] Why do fully qualified names have to be used when dynamically assessing namespaced elements?

查看:85
本文介绍了在动态评估命名空间元素时,为什么必须使用完全限定的名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直试图理解名称空间和动态语言功能(来自php.net手册).请考虑以下代码:

I have been trying to understand the chapter Namespaces and dynamic language features from php.net manual. Please consider the following code:

namespace Foo;

function strstr() {
    echo "My local ststr method called";
}

$a = 'strstr';
$a(); //This would call the global strstr method

按照手册,我必须去$a = 'Foo\strstr',但是我找不到原因.为什么php解释器在运行时无法知道$a = 'strstr';是在namespace Foo的上下文中定义的,就像直接执行strstr()一样,解释器还记得上下文在运行时是namespace Foo.

As per the manual, I have to go $a = 'Foo\strstr', but I can't find a reason for this. Why can't php interpreter at runtime know that $a = 'strstr'; was defined in the context of namespace Foo, just like executing strstr() straightaway the interpreter remember the context is namespace Foo at runtime.

我能想到的一个原因是,如果满足特定条件(例如,如果收到用户输入),则在事件上调用$a,因为该功能仅绑定到该事件而没有任何上下文信息.

One reason I can think of is $a to be called on an event if a certain condition(like if user input received) is met, because then the function is just bound to the event without any contextual information.

推荐答案

让我们检查生成的操作码(使用php -d opcache.opt_debug_level=0x10000 test.php):

Let's inspect the opcodes that are generated (using php -d opcache.opt_debug_level=0x10000 test.php):

代码:

<?php

namespace Foo;

function strstr() {
    echo "My local ststr method called";
}

$a = 'strstr';
$a();

strstr();

操作码:

$_main: ; (lines=7, args=0, vars=1, tmps=3)
    ; (before optimizer)
    ; /code/test.php:1-13
L0 (5):     NOP
L1 (9):     ASSIGN CV0($a) string("strstr")
L2 (10):    INIT_DYNAMIC_CALL 0 CV0($a)
L3 (10):    DO_FCALL
L4 (12):    INIT_NS_FCALL_BY_NAME 0 string("Foo\strstr")
L5 (12):    DO_FCALL
L6 (13):    RETURN int(1)

Foo\strstr: ; (lines=2, args=0, vars=0, tmps=0)
    ; (before optimizer)
    ; /code/test.php:5-7
L0 (6):     ECHO string("My local ststr method called")
L1 (7):     RETURN null

如您所见,$a()正在使用INIT_DYNAMIC_CALL操作码.如果传递的函数名称是字符串,则将其视为完全合格.

As you can see $a() is using the INIT_DYNAMIC_CALL opcode. When the passed function name is a string, it is treated as being fully qualified.

另一方面,strstr()使用INIT_NS_FCALL_BY_NAME操作码,并在传递给它的当前名称空间中解析名称.执行后,它将首先查找该名称(Foo\strstr),当该名称不存在时,它将回退到全局名称空间.

On the other hand strstr() uses the INIT_NS_FCALL_BY_NAME opcode, with the name resolved in the current namespace passed to it. Upon execution it will first look for that name (Foo\strstr), and when that does not exist it will fall back to the global namespace.

这篇关于在动态评估命名空间元素时,为什么必须使用完全限定的名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆