您能否在 PHP 中解决超出范围的后期静态绑定?
Can you resolve late static bindings out of scope in PHP?
我终于发现自己了解了范围和上下文,以及它们之间的区别,但现在我遇到了问题。
我在 parent class 中有一个由 child class 继承的静态方法。当我从 child 调用该方法时,我希望能够在 parent 中分辨出哪个 child 调用了它。
后期静态绑定,对吧?凉爽的。像这样:
class Daddy {
public static function madSkillz() {
var_dump( static::class );
}
}
class Sonny extends Daddy {}
Sonny::madSkillz();
在输出中,我看到:
string(5) "Sonny"
万岁,正是我所希望的! 但是...现在假设我从 parent 静态方法中调用了一个函数。我可以使用 debug_backtrace
找出调用了静态方法,但不幸的是我看到了声明 class,而不是范围。
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
object 并调用其他方法,但我需要确保我使用的是正确的范围,应该是Sonny
,而不是Daddy
。
有没有办法不用将static::class
作为参数传递给GoToTheFair()
?
编辑: 我不想使用参数方法的原因是 GoToTheFair()
函数是我正在编码的库,而 classes Daddy
和 Sonny
是用户的。我不希望他们有选择自己范围的自由。
似乎不可能得到你想要的(在这种情况下),因为debug_backtrace()
使用常量__class__
来显示class名字。
在您的上下文中:
public static function madSkillz() {
var_dump( static::class ); // outputs : "Sonny"
var_dump( __class__ ); // outputs : "Daddy"
GoToTheFair();
}
可能的解决方案1:
但是,如果调用方是对象而不是静态方法,您可以获得正确的 class。这是一个使用对象的例子:
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"
我终于发现自己了解了范围和上下文,以及它们之间的区别,但现在我遇到了问题。
我在 parent class 中有一个由 child class 继承的静态方法。当我从 child 调用该方法时,我希望能够在 parent 中分辨出哪个 child 调用了它。
后期静态绑定,对吧?凉爽的。像这样:
class Daddy {
public static function madSkillz() {
var_dump( static::class );
}
}
class Sonny extends Daddy {}
Sonny::madSkillz();
在输出中,我看到:
string(5) "Sonny"
万岁,正是我所希望的! 但是...现在假设我从 parent 静态方法中调用了一个函数。我可以使用 debug_backtrace
找出调用了静态方法,但不幸的是我看到了声明 class,而不是范围。
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
object 并调用其他方法,但我需要确保我使用的是正确的范围,应该是Sonny
,而不是Daddy
。
有没有办法不用将static::class
作为参数传递给GoToTheFair()
?
编辑: 我不想使用参数方法的原因是 GoToTheFair()
函数是我正在编码的库,而 classes Daddy
和 Sonny
是用户的。我不希望他们有选择自己范围的自由。
似乎不可能得到你想要的(在这种情况下),因为debug_backtrace()
使用常量__class__
来显示class名字。
在您的上下文中:
public static function madSkillz() {
var_dump( static::class ); // outputs : "Sonny"
var_dump( __class__ ); // outputs : "Daddy"
GoToTheFair();
}
可能的解决方案1:
但是,如果调用方是对象而不是静态方法,您可以获得正确的 class。这是一个使用对象的例子:
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"