2012-03-21 2 views
0

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

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

Любые предложения?

В принципе, я хочу знать, можно ли передать неизвестное количество параметров методу (без использования 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 Просто чтобы прояснить, я знаю, что могу использовать this метод реорганизовывать параметры как ссылки, но это означало бы, проходя все в качестве ссылки, даже если метод не требует этого - кое-что Я пытался избежать, но сейчас кажется маловероятным.

+1

«на всякий случай, если их нужно передать по ссылке» - какой-либо действительный пример этого? Любая причина этого? – zerkms

+0

@zerkms Методы, которые не входят в мой класс, передаются на другой класс, который нужно обрабатывать, а некоторые требуют, чтобы аргументы передавались по ссылке (см. Код). Я не включил этот класс, потому что я не контролирую Это. –

+0

См. Http://stackoverflow.com/questions/295016/is-it-possible-to-pass-parameters-by-reference-using-call-user-func-array, http://stackoverflow.com/questions/6259713/why-do-phps-call-user-func-function-not-support-through-by-reference – CBusBus

ответ

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

+0

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

+1

@cainmi Вид. Поскольку массив можно построить где угодно внутри вашего объекта или любым другим способом, таким как глобальная функция, этот подход не требует, чтобы вы передавали массив ссылок, только если вы влияете на массив на массив, будет существовать сфера действия метода и должны быть возвращены. – CBusBus

+0

Да, я понимаю, что вы имеете в виду. Учитывая, что массив, вероятно, будет создан внутри объекта Foo (в этом примере), могут возникнуть проблемы с любыми методами, которые фактически полагаются на изменение исходной переменной (через ссылку). –

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); 
    } 
} 
+0

Это в основном то, что делает код выше (хотя я допускаю только 2 параметра), это просто кажется немного неэлегантным. –

+0

Может быть, так, но я не думайте, что есть какое-то другое решение. – Rob

Смежные вопросы