PHP get_called_class() 替代

2022-08-30 21:11:42

我有一个抽象的PHP超类,它包含需要知道它在哪个子类下运行的代码。

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'

如果我调用该函数,这将起作用 - 但是,此代码将在PHP版本5.2.*中运行,因此该函数不可用。get_called_class()

有一些自定义的PHP实现,但它们都依赖于通过,解析文件名和行号,并运行正则表达式(因为编码人员不知道PHP 5.2有反射)来查找类名。此代码需要能够与php一起运行,即。不仅来自.php文件。(它需要从 shell 或语句开始工作。get_called_class()debug_backtrack()php -aeval()

理想情况下,解决方案无需将任何代码添加到子类即可工作...我能看到的唯一潜在解决方案是将以下代码添加到每个子类中,这显然是一个令人作呕的黑客攻击:

class FooBar extends Foo {
    static function _get_class_name() {
        return 'FooBar';
    }
}

编辑:等等,这似乎不起作用。这将是我最后的手段。任何人都可以想到类似于此解决方案的东西,可以为我提供所需的功能。也就是说,我愿意接受一个解决方案,它要求我为每个子类添加一个函数或变量,告诉它它的类名是什么。不幸的是,从超类调用似乎调用父类的实现,即使子类已经覆盖了它。self::_get_class_name()


答案 1

实际上,在执行超类方法时,了解实际的被调用(子)类通常是有帮助的,我不同意想要解决这个问题有什么问题。

例如,我的对象需要知道类名,但是它们对该信息执行的操作始终相同,如果我能够获得被调用的类名,则可以将其提取到超类方法中。甚至 PHP 团队也认为这足够有用,可以包含在 php 5.3 中。

据我所知,正确和非说教的答案是,在5.3之前,你必须做一些令人发指的事情(例如回溯),或者只是在每个子类中包含重复的代码。


答案 2

工作解决方案:

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

推荐