php 变量 类名,关于php:使用变量类名和静态方法时出错

本文探讨了在PHP5.4环境下,如何处理使用变量解析类名并调用其静态方法的问题。作者分享了不同尝试的方法,如call_user_func和ReflectionMethod,并揭示了解析错误背后的原理——解析器对动态类名处理的不同。

运行PHP 5.4,所以我没想到这个,但我遇到以下错误:

Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)

假设您有一个stdClass设置变量,如下所示:

$this->variable = new stdClass();

$this->variable->other = array('class' => 'helloworld');

现在,假设您要访问类helloworld的静态方法:

// Standard call

$x = helloworld::my_static_method();

// Call with variable class name

$x = $this->variable->other['class']::my_static_method();

使用变量类名调用上面的内容时,我收到解析错误。 奇怪的是,如果我执行以下操作,则不会出现错误:

$class = $this->variable->other['class'];

$x = $class::my_static_method();

对我来说这看起来很奇怪,有没有人能想到为什么在使用第一个例子和第二个例子时类名没有正确解析的原因?

can anyone think of a reason why the class name isn't resolving correctly when using the first example versus the second?

PHP解析器不支持这样的语法,而这仅仅是全部。这是因为解析器在历史上已经发展。我不能给出更多理由。

这将是使用PHP 7,您可以看到这些语法细节上的一些更改更多地工作在您的预期方向统一变量语法:

($variable->other['class'])::my_static_method();

但在此之前,您可以在call_user_func的帮助下解决这个问题:

call_user_func([$variable->other['class'], 'my_static_method']);

call_user_func($variable->other['class'] . '::my_static_method');

或者当你自己编写时,通过创建一个变量:

$class = $variable->other['class'];

$class::my_static_method();

甚至是一个看起来不同的变量:

${(int)!${0}=$variable->other['class']}::my_static_method();

相关材料:

PHP中的关联数组的插值(双引号字符串)

感谢您的解释。很高兴看到他们将支持PHP 7的一些更奇特的语法使用。

我不会说PHP 7的语法是异国情调,甚至反过来说:它更加一致。而且我很高兴这终于被解决了:)

这不起作用($this->variable->other['class']::my_static_method()),因为它实际上是直接使用字符串作为类名。它首先将它分配给变量时起作用,因为它然后被评估为类名。

您还可以查看使用ReflectionMethod调用以调用该方法,在这种情况下,您不必在使用它之前将类名存储在变量中。这是关于它的文档:http://php.net/manual/en/class.reflectionmethod.php和invoke方法(传入NULL表示静态方法)http://php.net /manual/en/reflectionmethod.invoke.php

以下是一些调用函数的方法示例:

class helloworld{

public static function my_static_method($i = 0){

echo"Here:".$i;

}

}

class Foo{

private $variable;

public function __construct(){

//Create a new class

$this->variable = new stdClass();

//Create a new property of the class, storing an array

$this->variable->other = array('class' => 'helloworld');

//Call function statically

$x = helloworld::my_static_method(1); //Outputs:"Here: 1"

//Store class name in a variable before use

$class = $this->variable->other['class'];

$y = $class::my_static_method(2); //Outputs:"Here: 2"

//Using a ReflectionMethod, you can call the function this way, too

$z = new ReflectionMethod($this->variable->other['class'], 'my_static_method');

$z->invoke(null, 3); //Outputs:"Here: 3"

}

}

//Instantiate new Foo class

new Foo();

有意思 - 我想我只是好奇为什么(在你的例子中)$class正确解析,但$this->variable->other['class']没有?在我看来,两个变量都解析为字符串helloworld。在你的评论中,"......它实际上是直接使用一个字符串作为类名。当你首先将它分配给一个变量时,它会起作用,因为它会被评估为类名。"为什么他们都没有被评估为班级名称?

它也很有趣,因为调用new $this->variable->other['class']()有效......不会属于同一个问题吗?

所以,有趣的是,当你使用$this->variable->other['class']时,它被评估为一个字符串。字符串没有::方法(即解析器不识别字符串的静态方法调用),这就是您需要使用变量的原因(在这种情况下,解析器能够将变量内容评估为class,和静态方法调用工作)。使用第二条注释,因为您不再使用静态方法调用,$this->variable->other['class']()按预期工作。

你可以在这里看到一些关于动态语言特性的信息(尽管它是基于命名空间的文档):php.net/manual/en/language.namespaces.dynamic.php以及类引用文档:php.net / manual /en/language.oop5.basic.php

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值