简体   繁体   English

以下对call_user_func_array()的调用是否有效?

[英]Does the following call to call_user_func_array() work?

I have a couple of libraries that use code similar to the following one. 我有几个库,它们使用的代码类似于以下代码。

$args = array_merge(array(&$target, $context), $args);
$result = call_user_func_array($callback, $args);

The code is different in both the cases, but the code I shown is what essentially is done. 两种情况下的代码都不同,但是我所展示的代码实际上是完成的。 The $callback function uses the following signature: $callback函数使用以下签名:

function callback(&$target, $context);

Both the libraries document that, and third-party code (call it plug-in, or extension) adopts that function signature, which means none of the extensions defines the callback as, eg, function my_extension_loader_callback($target, $context) . 库都说明和第三方代码(称为插件或扩展)都采用了该函数签名,这意味着没有一个扩展将回调定义为例如function my_extension_loader_callback($target, $context)

What confuses me are the following sentence in the documentation for call_user_func_array() . 使我感到困惑的是call_user_func_array()的文档中的以下句子。

Before PHP 5.4, referenced variables in param_arr are passed to the function by reference, regardless of whether the function expects the respective parameter to be passed by reference. 在PHP 5.4之前,param_arr中的引用变量通过引用传递给函数,无论该函数是否希望通过引用传递各个参数。 This form of call-time pass by reference does not emit a deprecation notice, but it is nonetheless deprecated, and has been removed in PHP 5.4. 这种形式的调用时按引用传递不会发出弃用通知,但是仍然不推荐使用,并且已在PHP 5.4中删除。 Furthermore, this does not apply to internal functions, for which the function signature is honored. 此外,这不适用于内部功能,为此必须遵循功能签名。 Passing by value when the function expects a parameter by reference results in a warning and having call_user_func() return FALSE . 函数通过引用期望参数时按值传递会导致警告,并使call_user_func()返回FALSE

In particular, the highlighted sentence seems to suggest that is not done for functions define in PHP code. 特别是,突出显示的句子似乎暗示着对PHP代码中定义的函数不执行此操作。

Does using call_user_func_array() in this way work in PHP 5.4? 以这种方式使用call_user_func_array()是否可以在PHP 5.4中使用?

When using call_user_func_array , passing by value when a function expects a reference is considered an error, in newer versions of PHP. 在较新版本的PHP中,使用call_user_func_array ,如果函数需要引用, call_user_func_array值传递被视为错误。

This was valid PHP code before PHP 5.3.3: 在PHP 5.3.3之前,这是有效的PHP代码:

//first param is pass by reference:
my_function(&$strName){
}

//passing by value, not by reference, is now incorrect if passing by reference is expected:
call_user_func_array("my_function", array($strSomething));

//correct usage
call_user_func_array("my_function", array(&$strSomething));

The above pass by value is no longer possible without a warning (my project is also set to throw exceptions on any kind of error (notice, warning, etc).) so I had to fix this. 上面的按值传递没有警告就不再可能(我的项目也被设置为对任何类型的错误(通知,警告等)抛出异常。)因此,我必须解决此问题。

Solution I've hit this problem and this is how I solved it (I have a small RPC server, so there is no such thing as referenced values after deserializing params): 解决方案我遇到了这个问题,这就是我解决的方法(我有一个小型RPC服务器,因此在反序列化参数后没有诸如引用值之类的东西):

//generic utility function for this kind of situations
function &array_make_references(&$arrSomething)
{ 
    $arrAllValuesReferencesToOriginalValues=array();
    foreach($arrSomething as $mxKey=>&$mxValue)
        $arrAllValuesReferencesToOriginalValues[$mxKey]=&$mxValue;
    return $arrAllValuesReferencesToOriginalValues;
}

Although $strSomething is not passed by reference, array_make_references will make it a reference to itself: 尽管$strSomething没有通过引用传递,但array_make_references会将其作为对自身的引用:

call_user_func_array("my_function", array_make_references(array($strSomething)));

I think the PHP guys were thinking of helping people catch incorrectly called functions (a well concealed pitfall), which happens often when going through call_user_func_array . 我认为PHP专家们正在考虑帮助人们捕获被错误调用的函数(一个隐蔽的陷阱),这通常在通过call_user_func_array时发生。

If call_user_func_array() returns false you have a problem, otherwise everything should be fine. 如果call_user_func_array()返回false ,则说明您有问题,否则一切都很好。

Parameters aren't passed by reference by default anymore, but you do it explicitly. 默认情况下,不再通过引用传递参数,但是您可以显式地进行传递。 The only trouble could be that your reference gets lost during array_merge() , haven't tested that. 唯一的麻烦可能是您的引用在array_merge()期间丢失了,还没有测试。

I've found this same problem when upgrading to PHP5.4 when there were several sites using call_user_func_array with arguments passed by reference. 当有多个站点使用通过引用传递参数的call_user_func_array时,我升级到PHP5.4时发现了同样的问题。

The workaround I've made is very simple and consists on replacing the call_user_func_array itself with the full function call using eval(). 我所做的解决方法非常简单,它包括使用eval()用完整的函数调用替换call_user_func_array本身。 It's not the most elegant solution but it fits the purpose for me :) 这不是最优雅的解决方案,但适合我的目的:)

Here's the old code: 这是旧的代码:

call_user_func_array($target, &$arguments);

Which I replace with: 我替换为:

$my_arguments = '';
for ($i=0; $i<count($arguments); $i++) {
    if ($i > 0) { $my_arguments.= ", "; }
    $my_arguments.= "\$arguments[$i]";
}
$evalthis = " $target ( $my_arguments );";
eval($evalthis);

Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM