确定调用函数的命名空间

时间:2011-12-15 10:46:57

标签: php oop namespaces

我想知道在调用函数时是否可以确定当前命名空间是什么。我有这个函数声明:

<?php
namespace Site\Action;
function add ($hook, $function) {
    /**
     * determine the namespace this was called from because
     * __NAMESPACE__ is "site\action" :(
     */
     if (is_callable($function))
         call_user_func($function);
}
?>

在另一个档案中:

<?php
namespace Foo;
function bar () {
}
?>

让我们说我将此作为我的程序代码:

<?php
namespace Foo;
Site\Action\add('hookname', 'bar');
?>

假设在这种情况下Bar旨在解析为Foo\bar,因为那是从它调用的命名空间,这是有意义的。

这又是一个很长的解释,是否可以确定调用Site\Action\add()的活动命名空间?

提前致谢。

3 个答案:

答案 0 :(得分:4)

您要找的是:ReflectionFunctionAbstract::getNamespaceName

如果你想知道你来自哪里debug_backtrace()是你的朋友。

以下内容可以解决您的难题:

function backtrace_namespace() 
{
    $trace = array();
    $functions = array_map(
        function ($v) {
            return $v['function'];
        },
        debug_backtrace()
    );
    foreach ($functions as $func) {
        $f = new ReflectionFunction($func);
        $trace[] = array(
            'function' => $func, 
            'namespace' =>  $f->getNamespaceName()
        );
    }
    return $trace;
}

只需从任何地方调用它即可查看回溯。 我按如下方式修改了“程序”代码文件:

namespace Foo;

function bar () 
{
    var_export(backtrace_namespace());
}

/** The unasked question: We need to use the fully qualified name currently. */
function go() 
{
    \Site\Action\add('hookname', 'Foo\\bar');
}

go();

包含此文件的结果将在stdout上显示以下内容:

array (
    0 =>
    array (
        'function' => 'backtrace_namespace',
        'namespace' => '',
    ),
    1 =>
    array (
        'function' => 'Foo\\bar',
        'namespace' => 'Foo',
    ),
    2 =>
    array (
        'function' => 'call_user_func',
        'namespace' => '',
    ),
    3 =>
    array (
        'function' => 'Site\\Action\\add',
        'namespace' => 'Site\\Action',
    ),
    4 =>
    array (
        'function' => 'Foo\\go',
        'namespace' => 'Foo',
    ),
)

现在为奖励积分回答隐藏的问题:

如何解析调用命名空间以避免使用完全限定的函数名作为参数?

以下内容允许您按预期调用该功能:

 Site\Action\add('hookname', 'bar');

没有得到可怕的:

  

警告:call_user_func()期望参数1是有效的回调,找不到函数'bar'或函数名无效

所以在你重新设计之前试试这个尺寸:

namespace Site\Action;

function add($hook, $function) 
{
    $trace = backtrace_namespace();
    $prev = (object) end($trace);

    $function = "$prev->namespace\\$function";

    if (is_callable($function))
        call_user_func($function);
}

我认为没有理由不使用debug_backtrace,这就是它的用途。

的nJoy!

答案 1 :(得分:1)

如果您使用闭包而不是静态函数,您可以随时询问反射API

namespace A;
$closure = function($word = 'hello')
{
    return $word;
};

...

$r = new ReflectionFunction($closure);
print $r->getNamespaceName();

答案 2 :(得分:0)

我不知道我是否遗漏了一些东西,但有了这个:

http://php.net/manual/en/reflectionclass.getnamespacename.php,我认为您可以获得正在使用的对象的命名空间。