我一直在阅读 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()
,当然也作为数组元素按值传递给testFunction()
via call_user_func_array()
。这会导致警告,因为testFunction()
需要引用。
到处乱窜,一些额外的细节浮出水面。定义,如果写成通过__callStatic()
引用返回 ( public static function &__callStatic()
) 没有可见的效果。此外,将$arguments
数组的元素重铸__callStatic()
为引用,我们可以看到这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()
魔法中的一个“错误”。我仔细阅读了现有或相关问题的错误数据库,并找到了一个,但无法再次找到它。我正在考虑发布另一份报告,或请求重新打开现有报告。