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:
<?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);
}
?>
And on another file:
<?php
namespace Foo;
function bar () {
}
?>
And let's say I have this as my procedural code:
<?php
namespace Foo;
Site\Action\add('hookname', 'bar');
?>
It would make sense to assume that Bar in this case was intended to resolve as Foo\bar since that was the namespace it was called from.
That was a long explanation so again, is it possible to determine the active namespace where Site\Action\add() was called from?
Thanks in advance.
Declaring a namespace is as simple as using the namespace keyword. A namespace name should obey the same rules as other identifiers in PHP. Therefore, a namespace must start with a letter or underscore, followed by any number of letters, numbers, or underscores. // Regular PHP code goes here, anything goes!
A namespace is a hierarchically labeled code block holding a regular PHP code. A namespace can contain valid PHP code. Namespace affects following types of code: classes (including abstracts and traits), interfaces, functions, and constants. Namespaces are declared using the namespace keyword.
Note: Namespace names are case-insensitive. Note: The Namespace name PHP , and compound names starting with this name (like PHP\Classes ) are reserved for internal language use and should not be used in the userspace code.
In computing, a namespace is a set of signs (names) that are used to identify and refer to objects of various kinds. A namespace ensures that all of a given set of objects have unique names so that they can be easily identified.
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:
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With