提问人:Boom 提问时间:4/7/2015 最后编辑:Boom 更新时间:4/9/2015 访问量:536
结合func_get_args、call_user_func_array和按引用传递
Combining func_get_args, call_user_func_array, and Pass By Reference
问:
我今天在 PHP 5.3.29 中做了一些有点棘手的事情。我所处的场景是,我必须链接 、 ,并通过引用传递一些参数。func_get_args
call_user_func_array
对简化方案的尝试如下所示:
调用方:.php
//* Caller Setup *//
// Define which Modules call which Hooks
global $hooks = array(
'hookA' => array('moduleA', 'moduleB'),
'hookB' => array('moduleA')
);
// Generically calls any Hook for all Modules
function caller_call_hook($hook, $by_reference = array())
{
// Use Hooks Array
global $hooks;
// Initialize Return Array
$values = array();
// Determine the Arguments for the Function Call
$args = func_get_args();
// Remove $hook and $by_reference from the Arguments
unset($args[0], $args[1]);
$args = array_values($args); // Collapse Array
// Map specified Arguments by Reference
foreach($by_reference as $index)
$args[$index] =& $args[$index];
// Call each Embedded Hook
foreach($hooks[$hook] as $module)
$values[$module] = call_user_func_array($module . '_' . $hook, $args);
// Return all Values
return $values;
}
//* Caller Triggers *//
function caller_hook_A($paramA, $paramB)
{
caller_call_hook('hook_A', array(), $paramA, $paramB);
}
function caller_hook_B(&$paramA)
{
caller_call_hook('hook_B', array(0), $paramA);
}
模块A.php
function moduleA_hook_A($paramA, $paramB) { ... }
function moduleA_hook_B(&$paramA) { ... }
模块B.php
function moduleB_hook_A($paramA, $paramB) { ... }
执行所有这些操作会引发警告:
Warning: Parameter 1 to moduleA_hook_B() expected to be a reference, value given in caller_call_hook()
我怎样才能使这项工作按预期进行?
只是为了提供一些关于这里实际发生的事情的背景:
我正在一个由框架调用的框架中工作。我基本上将调用方用作临时的“代码中心”,其中单独处理代码中的各种功能。caller_hook_*
不,我不能将这个项目拆分为多个项目。这是强加在我身上的限制。通常,这将是我会采取的路线。
这些功能基本上是内部功能,我希望能够轻松打开和关闭。它们是故意分开的文件,因为模块本身没有交叉,只是它们有时使用相同的钩子。module*
钩子本身的所有配置都在变量中处理(这是一个简化版本。通常每个模块还有函数属性、模块属性等,但这不是这个特定问题所必需的。$hooks
我试图尽可能地保持这种普遍性。我知道我可以把所有东西都推到各自的函数中,但是随着这个项目的发展,如果独立的功能聚集在一起,这些钩子将变得难以维护。caller_hook_*
一些钩子在他们的一些参数上使用传递引用,因此我需要能够指定哪些钩子。到目前为止,我所做的一切都适用于所有仅传递值的函数。
我也不想使用呼叫时间传递引用。
答:
我最终让它起作用了,尽管这是一个奇怪的解决方案。
我走在正确的轨道上,只是稍微偏离了一点。
我改变了这个:
// Map specified Arguments by Reference
foreach($by_reference as $index)
$args[$index] =& $args[$index];
对此:
// Map specified Arguments by Reference
$refs = array();
foreach($args as $key => &$value)
$refs[$key] =& $value;
还有这个:
// Call each Embedded Hook
foreach($hooks[$hook] as $module)
$values[$module] = call_user_func_array($module . '_' . $hook, $args);
对此:
// Call each Embedded Hook
foreach($hooks[$hook] as $module)
$values[$module] = call_user_func_array($module . '_' . $hook, $refs);
这是一个有点奇怪的修复,但它可以完成工作。事实证明,我不需要这个变量。$by_reference
评论
$args[$index] =& $args[$index]
$args[$index] =& $by_reference[$index];