【问题标题】:Determine the name of the calling class (parent or child) in parent class method在父类方法中确定调用类(父类或子类)的名称
【发布时间】:2016-12-15 23:23:59
【问题描述】:

寻找一种干净的方法来确定调用父类中方法的方法的类(在这种情况下,是父类或子类)。

我认为后期静态绑定可以处理这个问题,但似乎这只适用于直接调用静态方法,而不是从实例化对象的方法中。

考虑以下几点:

abstract class ParentClass {

    public function parentMethod() {
        self::_log("parent.non.static");
    }

    public static function parentStatic() {
        self::_log("parent.static");
    }

    public static function getClassName() {
        return __CLASS__;
    }

    protected static function _log($key) {
        $prefix = 'graphite.key.prefix';
        $class  = static::getClassName(); // gets the object's class, not calling class

        $g_key = "{$prefix}.{$class}.{$key}";
        echo "{$g_key} \n";

        // Graphite::increment($g_key);
    }
}

class ChildClass extends ParentClass {

    public function childMethod() {
        self::_log("child.non.static");
    }

    public static function childStatic() {
        self::_log("child.static");
    }

    public static function getClassName() {
        return __CLASS__;
    }
}


$obj = new ChildClass;

$obj->childMethod();           // graphite.key.prefix.ChildClass.child.non.static
$obj->parentMethod();          // graphite.key.prefix.ChildClass.parent.non.static

ParentClass::parentStatic();   // graphite.key.prefix.ParentClass.parent.static
ChildClass::childStatic();     // graphite.key.prefix.ChildClass.child.static

寻找一种简洁的方法来获取调用 _log() 方法的类,而无需将其作为参数传入。根本不必是静态的,但我在玩后期静态绑定,因为我认为这会起作用,但它只是获取实例化对象的名称,而不是调用方法的子/父类_log() 方法:-/

编辑:

为了清楚起见,我是在从实例化对象中获取调用 _log() 的方法的类名之后(如 parentMethod() 和 childMethod())不关心 _log() 是静态的还是不是。如果这能让事情变得更容易,那很好。但是静态 ParentClass::parentStatic() 和 ChildClass::childStatic() 只是为了显示后期静态绑定以及我认为可能有效的方法,而不是在实例化对象中调用

【问题讨论】:

  • get_class($this) 也许?
  • @JonathanKuhn 在静态方法中没有$this
  • @Barmar OP 特别指出它不必是静态的。
  • get_class($this) 不起作用,因为它将返回为 $obj 实例化的对象的名称,即 ChildClass,并且永远不会返回 ParentClass
  • 知道了,所以不仅仅是孩子打电话给父母。它是调用父级的子级,它调用自身下的另一个方法。在这种情况下,您需要父母。比如$instance->childMethod() 调用parent::parentMethod1() 调用self::parentMethod2()。在parentMethod2 中,您想表明它是由parentMethod1(或者实际上只是父级)调用的。如果是这样的话,我知道的唯一方法就是解析debug_backtrace()。虽然,考虑到调用函数/类总是在关键 1 上,这并不是那么糟糕。

标签: php


【解决方案1】:

get_class 将获取类实例的类名。这也可以在类中的$this 上调用。如果您有一个扩展/实现另一个类的类,$this 将引用实例化的类,即子类。

另一种选择是使用debug_backtrace 来获取通向您当前所在位置的函数堆栈。您可以解析返回的数组以获取所需的任何内容,包括行号、类、函数、方法等。

【讨论】:

  • 这适用于非静态方法,但静态方法中没有$this
  • 对,所以和这里发生的事情一样。它将获取实例化对象的类名(在本例中为 ChildClass),而不是调用该方法的类。并且解析 debug_backtrace 效率非常低,而且不是很干净,所以这不是我所追求的。那时我宁愿将课程作为参数传递
【解决方案2】:

http://php.net/manual/en/function.get-called-class.php

class One {
    public static function test() {
        echo get_called_class() . PHP_EOL;
    }
}

class Two extends One {}

One::test();
Two::test();

输出:

One
Two

此外,根据文档static::class 中的最高评论,PHP 5.5 也可以使用。

【讨论】:

  • 这和我的一样。我正在寻找从实例化对象中调用 _log() 方法的非静态方法的类名......从类外部调用它就像这样,obv
  • @giantNinja 那么在_log() 方法中你想获取调用方法的名称吗?
  • @giantNinja 正如你所说的“解析 debug_backtrace 效率极低而且不是很干净”,我同意这一点。我的日志函数调用通常看起来像$this->log("[%s] A thing happened with %s!", [__METHOD__, $somevar], 'crit');,它被输入sprintf() 以生成最终消息。
  • 是的,我的也是...我在石墨中记录了一些东西,部分关键是我正在调用_log() 方法的类是我想要能够使用,就像我调用$this->_log('foo.key', __CLASS__) 之类的_log() 方法并将第二个参数用作_log() 中的键的一部分,但我试图避免必须为每个方法调用传递它。这不是世界末日,但这只是我认为可以轻松完成的事情,但现在我想
  • @giantNinja 你总是可以在function _log() { /* ... */; parent::_log(); } 中对你所有的课程进行硬性插入,并且每个课程只需要写一次额外的位。 :P
猜你喜欢
  • 2016-02-14
  • 2011-09-04
  • 1970-01-01
  • 2012-02-22
  • 1970-01-01
  • 1970-01-01
  • 2020-01-14
  • 1970-01-01
  • 2017-11-09
相关资源
最近更新 更多