Determine what namespace the function was called in

后端 未结 3 568
心在旅途
心在旅途 2021-01-12 10:56

I was wondering if it was possible to determine what the current namespace was when the function was being called. I have this function declaration:



        
相关标签:
3条回答
  • 2021-01-12 11:31

    If you were using closures instead of static functions you can always ask the reflection API

    namespace A;
    $closure = function($word = 'hello')
    {
        return $word;
    };
    
    ...
    
    $r = new ReflectionFunction($closure);
    print $r->getNamespaceName();
    
    0 讨论(0)
  • 2021-01-12 11:31

    i don't know if i'm missing something, but with this:

    http://php.net/manual/en/reflectionclass.getnamespacename.php, i think that you can get namespace of the object you are using.

    0 讨论(0)
  • 2021-01-12 11:40

    What you are looking for is : ReflectionFunctionAbstract::getNamespaceName

    If you want to know where you're coming from debug_backtrace() is your friend.

    The following should solve your puzzle:

    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;
    }
    

    Just call it from anywhere to see the backtrace. I modified your "procedural" code file as follows:

    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();
    

    The Result from including this file will be the following on 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',
        ),
    )
    

    Now for bonus points the answer to the hidden question:

    How do I resolve the calling namespace to avoid using fully qualified function name as argument?

    The following will allow you to call the function as you intended:

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

    Without getting the dreaded:

    Warning: call_user_func() expects parameter 1 to be a valid callback, function 'bar' not found or invalid function name

    So before you redesign try this on for size:

    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);
    }
    

    I see no reason why debug_backtrace should not be used, this is what it is there for.

    nJoy!

    0 讨论(0)
提交回复
热议问题