Динамични функции, променливи входове

Точно сега, да кажем, че имам код, подобен на този...

$some_var=returnsUserInput();

function funcA($a) {...}
function funcB($a,$b) {...}
function funcC($a,$b,$c) {...}

$list[functionA] = "funcA";
$list[functionB] = "funcB";
$list[functionC] = "funcC";

$temp_call = list[$some_var];

//Not sure how to do this below, just an example to show the idea of what I want.
$temp_call($varC1,varC2,$varC3);
$temp_call($varB1,varB2);
$temp_call($varA1);

Проблемът ми започва тук, как мога да посоча правилните променливи в аргументите в зависимост от тях? Имам няколко мисли, като например създаване на списък за всяка функция, която ги определя, но наистина бих искал да видя елегантно решение за това.


person Incognito    schedule 12.07.2010    source източник
comment
Как очаквате funcC() да се справи с извикване с един аргумент?   -  person Ignacio Vazquez-Abrams    schedule 12.07.2010
comment
възможен дубликат на Как може ли да накара функция да приема неограничен брой параметри в PHP?   -  person John Conde    schedule 12.07.2010
comment
@Igancio Това питам. Имам логика, за да избирам всяка функция въз основа на друга логика, но искам да мога да присвоя функцията и да я извикам с правилните аргументи.   -  person Incognito    schedule 12.07.2010
comment
@John Не, не това питам. Имам конкретен набор от данни от заявка, които искам да предам на конкретни функции (вече дефинирани в масив), но искам да мога да създам променлива функция, която също е динамично присвоена и предоставя специфични аргументи.   -  person Incognito    schedule 12.07.2010
comment
Не разбирам въпроса. $temp_call($var, $var, $var) е абсолютно добре в PHP.   -  person NikiC    schedule 13.07.2010
comment
Бъдете по-конкретни относно това, което имате, какво искате и как сте подготвени да стигнете до там. Като за начало, защо просто не можете да направите това, което сте направили във вашия примерен код?   -  person salathe    schedule 13.07.2010
comment
Това е объркан начин да се правят нещата, но това, което вярвам, че той се опитва да постигне, е система, която ще приеме произволно количество аргументи и няма да изведе грешка. Така че нещо като: ?func=functionA&varC1=test&varC2=test2 (разбира се, ако това се извика на функция от този масив, който приема само 1 параметър, тогава той ще получи грешка) Има няколко опции, като func_get_args и предаване на масив вместо отделни параметри.   -  person Kieran Allen    schedule 13.07.2010
comment
Не, той няма да получи грешка, ако предаде твърде много аргументи. PHP хвърля грешка само ако подаде твърде малко аргументи.   -  person NikiC    schedule 13.07.2010
comment
@kieran това е много близо до това, което се опитвам. По същество това е централизирана страница за целите на: мащабируемост, сигурност, поддръжка... Кратък масив от стойности може лесно да бъде манипулиран, сякаш е конфигурационен файл. Вече няма нужда да се тревожа за това как работи това в по-голяма система, ако мога да направя това много динамично. Причината, поради която не публикувах кода, е, че той навлиза в твърде много други области, като проверка на входа и дезинфекция, както и как се свързва в по-голяма система от влизания и групи за сигурност/и т.н.   -  person Incognito    schedule 13.07.2010


Отговори (3)


Трябва да използвате call_user_func или call_user_func_array.

<?php
// if you know the parameters in advance.
call_user_func($temp_call, $varC1, $varC2);
// If you have an array of params.
call_user_func_array($temp_call, array($varB1, $varB2));
?>
person David Pratte    schedule 12.07.2010
comment
Това изглежда като стъпка в правилната посока. След като си поиграя известно време с това, ще ви уведомя. Благодаря ти. - person Incognito; 13.07.2010
comment
И, моля, не използвайте call_user_func неща, освен ако не извиквате динамично метод, защото той има два проблема: може да не премине по референция и е бавен;) - person NikiC; 13.07.2010
comment
Благодаря, възнамерявам да използвам call_user_func_array, само за информация. - person Incognito; 13.07.2010

Искате ли нещо като следното?

function test()
{
    $num_args   =   func_num_args();

    $args       =   func_get_args();

    switch ($num_args) {
        case 0:
            return 'none';
        break;


        case 1: 
            return $args[0];

        break;

        case 2:
            return $args[0] . ' - ' . $args[1];
        break;

        default:

            return implode($args, ' - ');
        break;
    }
}

echo test(); // 'none'
echo test(1); // 1
echo test(1, 2); // 1 - 2
echo test(1, 2, 3); // 1 - 2 - 3

Ще действа като някакъв метод за делегиране.

Или какво ще кажете за просто приемане на масив вместо параметри?

function funcA($params) 
{
  extract($params);

  echo $a;
}

function funcB($params) 
{
  extract($params);

  echo $a, $b;
}

function funcC($params) 
{
  extract($params);

  echo $a, $b, $c;
}


$funcs = array('funcA', 'funcB', 'funcC');

$selected = $funcs[0];


$selected(array('a' => 'test', 'b' => 'test2'));

// or something like  (beware of security issues)
$selected($_GET);
person Kieran Allen    schedule 12.07.2010
comment
Не, те са 3 функции, а не 1. Всички те правят много различни неща. - person Incognito; 13.07.2010
comment
Мислех да приема масив, но ще трябва да променя вероятно половината кодова база, за да работи с това, а след това се справям с проблеми, при които може да имам различни функции и т.н. - person Incognito; 13.07.2010

Не можете и може би това е добре. Можете да намерите броя на аргументите с if/else.

if($temp_call == "funcA") { .....} elseif(...)...

person Stijn Leenknegt    schedule 12.07.2010
comment
Не е въпрос на броене на аргументи. Те не са var1, var2 и var3. Те са varA1, varA2, varA3 като серия, varB1, varB2 като серия и varC1 като своя собствена серия. Мога да имам VarQ1, varQ2 и super_duper като серия. - person Incognito; 13.07.2010