I've got an Abstract PHP superclass, which contains code that needs to know which subclass its running under.
class Foo {
static function _get_class_name() {
return get_called_class();
//works in PHP 5.3.*, but not in PHP 5.2.*
}
static function other_code() {
//needs to know
echo self::_get_class_name();
}
}
class Bar extends Foo {
}
class FooBar extends Foo {
}
Bar::other_code(); // i need 'Bar'
FooBar::other_code(); // i need 'FooBar'
This would work if I called the function get_called_class()
-- however, this code is going to be run in PHP version 5.2.*, so that function is not available.
There's some custom PHP implementations of get_called_class()
out there, but they all rely on going thru the debug_backtrack()
, parsing a file name & line number, and running a regex (as the coder is not aware that PHP 5.2 has reflection) to find the class name. This code needs to be able to be run with php, ie. not only from a .php file. (It needs to work from a php -a
shell, or an eval()
statement.)
Ideally, a solution would work without requiring any code to be added to the subclasses… The only potential solution I can see though is adding the following code to each subclass, which is obviously a disgusting hack:
class FooBar extends Foo {
static function _get_class_name() {
return 'FooBar';
}
}
EDIT: Wait, this doesn't even seem to work. It would've been my last resort. Can anybody think of something similar to this solution that'd get me the required functionality. Ie., I'm willing to accept a solution that requires me to add one function or variable to each subclass telling it what its class name is. Unfortunately, it seems that calling self::_get_class_name()
from the superclass calls the parent class' implementation, even if the subclass has overridden it.
I have asked a question like this before, because I wanted a parent to have a factory method that was something like this
But it always returned the parent class, not the inherited one.
I was told that it is not possible without late static binding. It was introduced in PHP 5.3. You can read the documentation.
In reality it is often helpful to know the actual called (sub)class when executing a superclass method, and I disagree that there's anything wrong with wanting to solve this problem.
Example, my objects need to know the class name, but what they do with that information is always the same and could be extracted into a superclass method IF I was able to get the called class name. Even the PHP team thought this was useful enough to include in php 5.3.
The correct and un-preachy answer, as far as I can tell, is that prior to 5.3, you have to either do something heinous (e.g. backtrace,) or just include duplicate code in each of the subclasses.
Working solution:
This hack includes the heinous use of debug_backtrace... not pretty, but it does the job:
This is not possible.
The concept of "called class" was introduced in PHP 5.3. This information was not tracked in previous versions.
As an ugly work-around, you could possibly use
debug_backtrace
to look into the call stack, but it's not equivalent. For instance, in PHP 5.3, usingClassName::method()
doesn't forward the static call; you have no way to tell this withdebug_backtrace
. Also,debug_backtrace
is relatively slow.The solution is:
However, I don't know if this sentence works in static functions. Give it a try and tell me your feedback.