Передайте переменное количество параметров без call_user_func_array () - PullRequest
0 голосов
/ 21 марта 2012

У меня проблема с кодом, связанная с тем, что я использую определенные библиотеки кода, которые я не могу изменить.

Я использую следующий код, чтобы передать выполнение любых неопределенных методов другому классу, и он работает нормально, но это похоже на удвоение затрат.

Есть предложения?

По сути, я хочу знать, возможно ли передать неизвестное количество параметров методу (без использования 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

EDIT Просто чтобы уточнить, я знаю, что могу использовать этот метод для перенастройки параметров в качестве ссылок, но это будет означать передачу всего в качестве ссылки, даже если метод не требует этого - чего я пытался избежать , но в настоящий момент кажется маловероятным.

Ответы [ 2 ]

1 голос
/ 21 марта 2012

Как прокомментировано в комментариях к сообщению в вопросе о ветке, это пример и не обязательно (вероятно) лучшая практика.

//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 () каждый раз, когда вам нужно передать элемент, который будет передан как ссылка, а не как значение.

1 голос
/ 21 марта 2012

Вы можете использовать что-то вроде этого:

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);
    }
}
...