为什么PHP';s call_user_func()函数不支持按引用传递?

为什么PHP';s call_user_func()函数不支持按引用传递?,php,reference,callback,language-design,Php,Reference,Callback,Language Design,为什么像call\u user\u func()这样的函数处理函数不支持通过引用传递参数 比如“注意call_user_func()的参数不是通过引用传递的。”我假设PHP开发人员有某种理由在这种情况下禁用该功能 他们是否面临技术限制?这是语言设计的选择吗?这是怎么发生的 编辑: 为了澄清这一点,这里有一个例子 <?php function more(&$var){ $var++; } $count = 0; print "The count is $count.\n"; m

为什么像
call\u user\u func()
这样的函数处理函数不支持通过引用传递参数

比如“注意call_user_func()的参数不是通过引用传递的。”我假设PHP开发人员有某种理由在这种情况下禁用该功能

他们是否面临技术限制?这是语言设计的选择吗?这是怎么发生的

编辑:

为了澄清这一点,这里有一个例子

<?php

function more(&$var){ $var++; }

$count = 0;
print "The count is $count.\n";

more($count);
print "The count is $count.\n";

call_user_func('more', $count);
print "The count is $count.\n";

// Output:
// The count is 0.
// The count is 1.
// The count is 1.
请参见以下内容:


在数组中传递引用可以正常工作。

更新的答案:

您可以使用:

call_user_func('more', &$count)
达到与以下相同的效果:

call_user_func_array('more', array(&$count))
出于这个原因,我(毫无根据地)相信
call\u user\u func
只是编译器时间的捷径。(即,在编译时,它会被后面的替换)

关于您的实际问题“为什么
call\u user\u func
设计成这样工作?”,请给出我的看法:

它可能与“为什么某些方法
strstrstrstr
和其他
stru替换
?”属于同一行,为什么数组函数
haystack,needle
和字符串函数
needle,haystack

这是因为PHP是由许多不同的人在很长一段时间内设计的,当时没有严格的标准

原始答案:

必须确保将数组中的变量也设置为引用

尝试此操作并记下
数组(&$t)
部分:

function test(&$t) {
    $t++;
    echo '$t is '.$t.' inside function'.PHP_EOL;
}

$t = 0;
echo '$t is '.$t.' in global scope'.PHP_EOL;

test($t);

$t++;
echo '$t is '.$t.' in global scope'.PHP_EOL;

call_user_func_array('test', array(&$t));

$t++;
echo '$t is '.$t.' in global scope'.PHP_EOL;
应输出:

$t is 0 in global scope
$t is 1 inside function
$t is 2 in global scope
$t is 3 inside function
$t is 4 in global scope

这个答案深深嵌入到PHP模型中引用的方式——不一定是实现,因为它可以变化很多,特别是在5。x版本中。我确信你已经听到了这些行,它们不像C指针,或者C++引用等等。基本上,当变量被赋值或绑定时,它可以在两种方式发生。通过值(在这种情况下,新变量绑定到包含旧值副本的新“框”中)或通过引用(在这种情况下,新变量绑定到与旧值相同的值框中)。无论我们谈论的是变量、函数参数还是数组中的单元格,这都是正确的

当你开始将引用传递到函数中时,事情开始变得有点麻烦了——很明显,目的是能够修改原始变量。很久以前,调用时间按引用传递(将引用传递到不需要的函数中的能力)已被弃用,因为未意识到它正在处理引用的函数可能会“意外”修改输入。将其提升到另一个级别,如果该函数调用第二个函数,则该函数本身不需要引用…然后所有内容都会断开连接。它可能会工作,但不能保证,并且可能会在某些情况下中断P版本

这就是
call\u user\u func()
的作用。假设您向其中传递一个引用(并获取与调用时间通过引用传递警告相关的参数)。然后您的引用将绑定到一个新变量
call\u user\u func()的参数
本身。然后,当调用目标函数时,它的参数不会绑定到预期的位置。它们根本不会绑定到原始参数。它们绑定到
call\u user\u func()声明中的局部变量。
call\u user\u func\u array()
也需要小心。将引用放在数组单元格中可能会有麻烦-因为PHP使用“写时复制”语义传递该数组,所以您无法确定数组是否不会在您下面被修改,副本是否不会与原始引用分离

我所看到的最有见地的解释(帮助我了解引用)是在PHP“通过引用传递”手册上的评论中:

基本上逻辑是这样的。您将如何编写自己版本的
call\u user\u func()
?-然后解释它如何与引用断开,以及在避免调用时间按引用传递时如何失败。换句话说,调用函数的正确方法(指定值,让PHP根据函数声明决定是传递值还是引用)在使用
call\u user\u func()
时不起作用-您正在调用两个函数,第一个是通过值,第二个是通过引用第一个函数中的值


仔细想想,您将对PHP引用有更深入的理解(如果可以的话,您将有更大的动力避开它)。

另一种可能的方式-by reference语法保持“正确”的方式:

$data = 'some data';
$func = 'more';
$func($more);

function more(&$data) {
  // Do something with $data here...
}

如果有人想知道,
call\u user\u func\u array()
和一系列参考资料是有效的。谢谢!我已经知道了这个解决方法;问题是为什么这样一个解决方法首先是必要的。我会把钱花在“设计决策”上,不多也不少。如果我在这个话题上遇到一些有趣的事情,我会更新我的答案。谢谢!但我想知道的不是“我如何通过call_user_func传递推荐信”,而是“为什么我必须通过call_user_func获得推荐信?”问题是关于PHP的设计,而不是它的用途。@Will,当您向数组中添加某些内容时,PHP默认情况下会复制它。因此,为了传递引用数组,您必须首先向数组中添加变量作为引用。谢谢,我理解。我编辑了这个问题以澄清它。@Will,我已更新了我的答案以反映您的更新ed Question感谢您,+1花时间更新您的答案。不过请注意,
call\u user\u func('more',&$count)
将抛出一条警告“按引用传递调用时间已被弃用-按值传递参数”除非php.ini中的allow\u call\u time\u pass\u reference设置为ON。这非常有帮助。很高兴我再次访问了这个问题。谢谢!