【发布时间】:2011-08-01 22:29:09
【问题描述】:
我一直在阅读关于 SO 和其他地方的文章,但我似乎找不到任何结论性的内容。
是否有任何方法可以有效地通过此调用堆栈进行引用,从而产生下面示例中描述的所需功能?虽然这个例子并没有试图解决它,但它确实说明了问题:
class TestClass{
// surely __call would result similarly
public static function __callStatic($function, $arguments){
return call_user_func_array($function, $arguments);
}
}
// note argument by reference
function testFunction(&$arg){
$arg .= 'bar';
}
$test = 'foo';
TestClass::testFunction($test);
// expecting: 'foobar'
// getting: 'foo' and a warning about the reference
echo $test;
为了激发潜在的解决方案,我将在此处添加摘要详细信息:
仅关注call_user_func_array(),我们可以确定(至少对于 PHP 5.3.1)您不能通过引用隐式传递参数:
function testFunction(&$arg){
$arg .= 'bar';
}
$test = 'foo';
call_user_func_array('testFunction', array($test));
var_dump($test);
// string(3) "foo" and a warning about the non-reference parameter
通过显式传递数组元素$test 作为引用,我们可以缓解这种情况:
call_user_func_array('testFunction', array(&$test));
var_dump($test);
// string(6) "foobar"
当我们使用__callStatic() 引入类时,通过引用的显式调用时间参数似乎按照我的预期进行,但会发出弃用警告(在我的 IDE 中):
class TestClass{
public static function __callStatic($function, $arguments){
return call_user_func_array($function, $arguments);
}
}
function testFunction(&$arg){
$arg .= 'bar';
}
$test = 'foo';
TestClass::testFunction(&$test);
var_dump($test);
// string(6) "foobar"
在TestClass::testFunction() 中省略引用运算符会导致$test 按值传递给__callStatic(),当然也会作为数组元素按值通过call_user_func_array() 传递给testFunction()。这会导致警告,因为 testFunction() 需要引用。
四处乱窜,一些额外的细节浮出水面。 __callStatic() 定义,如果写成通过引用返回 (public static function &__callStatic()) 没有可见效果。此外,将__callStatic() 中的$arguments 数组的元素重铸为引用,我们可以看到call_user_func_array() 的工作方式与预期有些相似:
class TestClass{
public static function __callStatic($function, $arguments){
foreach($arguments as &$arg){}
call_user_func_array($function, $arguments);
var_dump($arguments);
// array(1) {
// [0]=>
// &string(6) "foobar"
// }
}
}
function testFunction(&$arg){
$arg .= 'bar';
}
$test = 'foo';
TestClass::testFunction($test);
var_dump($test);
// string(3) "foo"
这些结果是预期的,因为 $test 不再通过引用传递,更改也不会传递回其范围。但是,这证实了call_user_func_array() 实际上按预期工作,并且问题肯定仅限于调用魔法。
进一步阅读,它似乎是 PHP 处理用户函数的一个“错误”,以及 __call()/__callStatic() 的魔法。我仔细阅读了现有或相关问题的错误数据库,并找到了一个,但无法再次找到它。我正在考虑发布另一份报告,或请求重新打开现有报告。
【问题讨论】:
-
看来这个问题更多地与
__call()魔法有关,而不是call_user_func_array()... 此外,似乎没有特别干净的解决方法。不过,欢迎提出任何想法。
标签: php pass-by-reference magic-methods dynamic-function