Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP get_called_class() alternative

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.

like image 374
Kenneth Ballenegger Avatar asked Aug 17 '10 00:08

Kenneth Ballenegger


3 Answers

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.

like image 61
rnr Tom Avatar answered Nov 18 '22 13:11

rnr Tom


Working solution:

function getCalledClass(){
    $arr = array(); 
    $arrTraces = debug_backtrace();
    foreach ($arrTraces as $arrTrace){
       if(!array_key_exists("class", $arrTrace)) continue;
       if(count($arr)==0) $arr[] = $arrTrace['class'];
       else if(get_parent_class($arrTrace['class'])==end($arr)) $arr[] = $arrTrace['class'];
    }
    return end($arr);
}
like image 28
alda78 Avatar answered Nov 18 '22 11:11

alda78


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, using ClassName::method() doesn't forward the static call; you have no way to tell this with debug_backtrace. Also, debug_backtrace is relatively slow.

like image 3
Artefacto Avatar answered Nov 18 '22 11:11

Artefacto