簡體   English   中英

以下對call_user_func_array()的調用是否有效?

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

我有幾個庫,它們使用的代碼類似於以下代碼。

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

兩種情況下的代碼都不同,但是我所展示的代碼實際上是完成的。 $callback函數使用以下簽名:

function callback(&$target, $context);

庫都說明和第三方代碼(稱為插件或擴展)都采用了該函數簽名,這意味着沒有一個擴展將回調定義為例如function my_extension_loader_callback($target, $context)

使我感到困惑的是call_user_func_array()的文檔中的以下句子。

在PHP 5.4之前,param_arr中的引用變量通過引用傳遞給函數,無論該函數是否希望通過引用傳遞各個參數。 這種形式的調用時按引用傳遞不會發出棄用通知,但是仍然不推薦使用,並且已在PHP 5.4中刪除。 此外,這不適用於內部功能,為此必須遵循功能簽名。 函數通過引用期望參數時按值傳遞會導致警告,並使call_user_func()返回FALSE

特別是,突出顯示的句子似乎暗示着對PHP代碼中定義的函數不執行此操作。

以這種方式使用call_user_func_array()是否可以在PHP 5.4中使用?

在較新版本的PHP中,使用call_user_func_array ,如果函數需要引用, call_user_func_array值傳遞被視為錯誤。

在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));

上面的按值傳遞沒有警告就不再可能(我的項目也被設置為對任何類型的錯誤(通知,警告等)拋出異常。)因此,我必須解決此問題。

解決方案我遇到了這個問題,這就是我解決的方法(我有一個小型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;
}

盡管$strSomething沒有通過引用傳遞,但array_make_references會將其作為對自身的引用:

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

我認為PHP專家們正在考慮幫助人們捕獲被錯誤調用的函數(一個隱蔽的陷阱),這通常在通過call_user_func_array時發生。

如果call_user_func_array()返回false ,則說明您有問題,否則一切都很好。

默認情況下,不再通過引用傳遞參數,但是您可以顯式地進行傳遞。 唯一的麻煩可能是您的引用在array_merge()期間丟失了,還沒有測試。

當有多個站點使用通過引用傳遞參數的call_user_func_array時,我升級到PHP5.4時發現了同樣的問題。

我所做的解決方法非常簡單,它包括使用eval()用完整的函數調用替換call_user_func_array本身。 這不是最優雅的解決方案,但適合我的目的:)

這是舊的代碼:

call_user_func_array($target, &$arguments);

我替換為:

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

希望這可以幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM