结合func_get_args、call_user_func_array和按引用传递

Combining func_get_args, call_user_func_array, and Pass By Reference

提问人:Boom 提问时间:4/7/2015 最后编辑:Boom 更新时间:4/9/2015 访问量:536

问:

我今天在 PHP 5.3.29 中做了一些有点棘手的事情。我所处的场景是,我必须链接 、 ,并通过引用传递一些参数。func_get_argscall_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_*

一些钩子在他们的一些参数上使用传递引用,因此我需要能够指定哪些钩子。到目前为止,我所做的一切都适用于所有仅传递值的函数。

我也不想使用呼叫时间传递引用

PHP 模块 钩子 传递

评论

0赞 Barmar 4/7/2015
应该做什么?某物如何成为对自身的参考?$args[$index] =& $args[$index]
0赞 Barmar 4/7/2015
那应该是吗?$args[$index] =& $by_reference[$index];
0赞 Boom 4/7/2015
我来自C++背景,所以我可能在这里错误地使用了引用。你会推荐什么?
0赞 Barmar 4/7/2015
我不明白这如何解释任何事情。您也不会在 C++ 中设置对自身的引用。
0赞 Boom 4/7/2015
好吧,我要做的是将数组中的元素更改为通过引用传递。这是如何实现的?

答:

0赞 Boom 4/9/2015 #1

我最终让它起作用了,尽管这是一个奇怪的解决方案。

我走在正确的轨道上,只是稍微偏离了一点。

我改变了这个:

// 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