php - 您可以解决 PHP 中超出范围的后期静态绑定(bind)吗?

标签 php reflection scope debug-backtrace

我终于发现自己正在学习范围和上下文以及它们之间的区别,但现在我遇到了问题。

我在父类中有一个由子类继承的静态方法。当我从子级调用该方法时,我希望能够在父级中告诉哪个子级调用了它。

后期静态绑定(bind),对吗?凉爽的。像这样:

class Daddy {
    public static function madSkillz() {
        var_dump( static::class );
    }
}

class Sonny extends Daddy {}

Sonny::madSkillz();

在输出中,我看到:

string(5) "Sonny"

万岁,正是我所希望的! 但是...现在假设我从该父静态方法中调用一个函数。我可以使用 debug_backtrace 来找出调用了静态方法,但不幸的是我看到了声明类,而不是范围。

function GoToTheFair() {
    var_dump( debug_backtrace() );
}

class Daddy {
    public static function madSkillz() {
        var_dump( static::class );
        GoToTheFair();
    }
}

class Sonny extends Daddy {}

Sonny::madSkillz();

这将打印输出:

string(5) "Sonny"
array(2) {
  [0]=>
  array(4) {
    ["file"]=>
    string(28) "/home/branja/Desktop/cry.php"
    ["line"]=>
    int(10)
    ["function"]=>
    string(11) "GoToTheFair"
    ["args"]=>
    array(0) {
    }
  }
  [1]=>
  array(6) {
    ["file"]=>
    string(28) "/home/branja/Desktop/cry.php"
    ["line"]=>
    int(16)
    ["function"]=>
    string(9) "madSkillz"
    ["class"]=>
    string(5) "Daddy"
    ["type"]=>
    string(2) "::"
    ["args"]=>
    array(0) {
    }
  }
}

我希望能够在 GoToTheFair() 中创建一个 ReflectionMethod 对象并调用其他方法,但我需要确保使用正确的范围, 应该Sonny,而不是Daddy

有没有一种方法可以在不将 static::class 作为参数传递给 GoToTheFair() 的情况下实现此目的?


编辑:我不想使用参数方法的原因是 GoToTheFair() 函数是我正在编码的库和类 DaddySonny 是用户的。我不希望他们有选择自己范围的自由。

最佳答案

似乎不可能得到你想要的(在这种情况下),因为 debug_backtrace()使用常量__class__来显示类名。

在您的上下文中:

public static function madSkillz() {
    var_dump( static::class ); // outputs : "Sonny"
    var_dump( __class__ ); // outputs : "Daddy"
    GoToTheFair();
}

可能的解决方案 1:

但是,如果调用者是对象而不是静态方法,您可以获得正确的类。这是使用对象的示例:

function GoToTheFair() {
    $trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT) ;
    $last  = $trace[1] ;
    var_dump(get_class($last['object'])) ;
}
class Daddy {
    public function madSkillz() {
        var_dump( static::class );
        GoToTheFair();
    }
}
class Sonny extends Daddy {}
(new Sonny)->madSkillz();

将输出:

"Sonny"
"Sonny"

可能的解决方案2:

您可以使用Singleton Pattern .

function GoToTheFair() {
    $trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT) ;
    $last  = $trace[1] ;
    var_dump(get_class($last['object'])) ;
}
class Daddy {

    private static $instance = null;
    private function __construct() {}

    public static function getInstance() {
        $class = static::class ;
        if (!isset(self::$instance))
            self::$instance = new $class();
        return self::$instance ;
    }
    public function madSkillz() {
        var_dump( static::class );
        GoToTheFair();
    }
}
class Sonny extends Daddy {}

Sonny::getInstance()->madSkillz();

将输出:

"Sonny"
"Sonny"

关于php - 您可以解决 PHP 中超出范围的后期静态绑定(bind)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48762122/

相关文章:

javascript - 如何用脚本更改ajximage.php?

php - 管理员找不到 PHP 扩展

reflection - Guice 对象上的类层次结构问题

java - 如何动态转换 Java 对象

sql - SQL游标中表变量的范围

java - 将 Java 匿名内部类转换为 Lambda 表达式后,范围会发生什么变化?

javascript - 如何在 Vue JS 中获取 main.js 文件中的全局数据?

php - Mysqli while 循环在明显非空结果集上返回空数组

php - 检查所有 $_POST 值以进行应答和打印

scala - 有没有办法将 Scala 反射中的两个等效类型转换为两个相等的类型?