不带call_user_func_array()传递可变数量的参数

时间:2012-03-21 03:12:45

标签: php parameter-passing

我遇到了一个代码问题,这个问题源于我使用的某些代码库无法更改。

我使用以下代码将任何未定义的方法的执行传递给另一个类,它工作正常,但似乎浪费了一倍。

有什么建议吗?

基本上我想知道是否可以将未知数量的参数传递给方法(不使用call_user_func_array(),以防它们需要通过引用传递)。我不是问如何使用func_get_args(),而是反过来。

或者我应该在第一个逻辑路径(list()代码)中再允许一些参数?

class Foo {
    __construct() {
        $this->external = new ClassThatIHaveNoControlOver();
    }

    function bar($name) {
        return 'Hi '.$name;
    }

    function __call($method, $arguments) {
        if (count($arguments) < 3) {
            // call_user_func_array won't pass by reference, as required by
            // ClassThatIHaveNoControlOver->foobar(), so calling the function
            // directly for up to 2 arguments, as I know that foobar() will only
            // take 2 arguments
            list($first, $second) = $arguments + Array(null, null);
            return $this->external->$method($first, $second);
        } else {
            return call_user_func_array(array($this->external, $method), $arguments);
        }
    }
}

$foo = new Foo();

$firstName = 'Bob';
$lastName = 'Brown';
echo $foo->bar($firstName); // returns Hi Bob as expected
echo $foo->foobar($firstName, $lastName); // returns whatever
        // ClassThatIHaveNoControlOver()->foobar() is meant to return

修改 只是为了澄清,我知道我可以使用this方法将参数重新设置为引用,但这意味着将所有内容作为引用传递,即使方法不需要它 - 我试图避免这种情况,但是目前似乎不太可能。

2 个答案:

答案 0 :(得分:1)

您可以使用以下内容:

public function __call($method, $params = array()) {
    switch (count($params)) {
        case 0:
            return $this->external->{$method}();
        case 1:
            return $this->external->{$method}($params[0]);
        case 2:
            return $this->external->{$method}($params[0], $params[1]);
        case 3:
            return $this->external->{$method}($params[0], $params[1], $params[2]);
        default:
            return call_user_func_array(array(&this->external, $method), $params);
    }
}

答案 1 :(得分:1)

正如帖子问题帖子的评论中所评论的那样,这是一个例子,并不一定(可能)是最佳实践。

//Some vars
$foo = "shoe";
$bar = "bucket";

//Array of references
$arr = Array(&$foo, &$bar);

//Show that changing variable value affects array content
$foo = "water";
echo $arr[0];

//Sample function
function fooBar($a)
{
    $a[0] = "fire";
}
//Call sample function
call_user_func("fooBar",$arr);

//Show that function changes both array contents and variable value by reference
echo $arr[0];
echo $foo;

在讨论中稍微扩展一下,再次不是最行业的标准方法,但它会完成这项工作。

function pushRefOnArray(&$arr, &$var, $key = false)
{
    if(isset($key))
        $arr[$key] = &$var;
    else
        $arr[] = &$var;
}

基本上,您可以动态构建数组并在需要传递要作为引用而不是值传递的项目时调用pushRefToArray()。