2

If I had two classes in separate namespaces (and therefor files), and they both called a function in the global namespace - is there any way to indentify which namespace called that function short of passing the value?

namespace A;
class Test { function run() { \func(); }

...

namespace B;
class Test { function run() { \func(); }

...

function func()
{
    // Did a class from "\A" call me or "\B"...?
}

My first thought was to use the __NAMESPACE__ constant. But that is computed in place so it would not solve this problem.

Xeoncross
  • 55,620
  • 80
  • 262
  • 364
  • 3
    Not sure why this is necessary, surely if the function has to do something different depending on where it's being called from, then you have two separate namespaced functions.... if it needs to do something to the different objects, then pass the objects to the function as an argument – Mark Baker Jan 13 '12 at 19:39
  • @Mark My thoughts exactly. I suppose you could inspect the callstack or use some kind of reflection. What you want is not supported in the language to my knowledge. – Halcyon Jan 13 '12 at 19:42
  • @Frits - plenty of better ways than debug_backtrace for equivalent requirement http://stackoverflow.com/questions/743686/determine-where-a-function-has-been-called-with-php (e.g. __ NAMESPACE __ constant being passed as an argument to the function – Mark Baker Jan 13 '12 at 19:47
  • It's an odd request I grant you, but PHP 5.4's traits will solve this problem soon. – Xeoncross Jan 13 '12 at 19:56
  • @Mark - Of course, but I thought the point was that the namespace is not passed in as an argument (which is not a good way to design functions by the way :p ). – Halcyon Jan 13 '12 at 19:57
  • @Frits, passing magic __ NAMESPACE __ is still a lot more efficient than debug bactrace, which is notoriously costly in performance... I'd be interested in knowing why it's needed though. – Mark Baker Jan 13 '12 at 20:01

2 Answers2

2

You could define versions of the function in each namespace that then calls func();

namespace A;
class Test { function run() { func(); }

...

namespace B;
class Test { function run() { func(); }

...

namespace A
{
    function func()
    {
        \func(__NAMESPACE__);
    }
}

namespace B
{
    function func()
    {
        \func(__NAMESPACE__);
    }
}

namespace 
{
    function func($namespace)
    {
        //work with $namespace
    }
}
CLo
  • 3,650
  • 3
  • 26
  • 44
  • You could also just define the different functionality for each namespace right into the different declarations of func() but at least this would hide the need to pass the namespace from the classes using func() – CLo Jan 13 '12 at 20:01
1

debug_backtrace() will show you the call stack. It also gives you the class name of the object that the calls were made from. You could parse this date out and find the namespace.

http://www.php.net/manual/en/function.debug-backtrace.php

function func()
{
    $trace = debug_backtrace();
    $class = $trace[1]['class']; //Should be the class from the previous function

    $arr = explode($class, "\");
    array_pop($arr);
    $namespace = implode($arr, "\");
}

Let me know if that works. It will probably only work if func() is called from inside an object or class.

CLo
  • 3,650
  • 3
  • 26
  • 44