Динамическое использование прототипов функций в PHP

#php #function-calls

Вопрос:

Я пишу конструкцию на PHP, в которой синтаксический анализатор определяет, какую функцию вызывать динамически, примерно так:

 // The definition of what to call
$function_call_spec = array( "prototype"  => "myFunction", 
                             "parameters" => array( "first_par"  => "Hello",
                                                    "second_par" => "World"));

// Dispatch
$funcPrototype = $function_call_spec["prototype"];
$funcPrototype(); // Here we call function 'myFunction'.
 

Все это прекрасно и шикарно. Но теперь наступает следующий шаг, передача параметров, которые я действительно не знаю, возможно ли это так, как я хочу это сделать. Однако меня никогда не перестает удивлять, на что способны языки сценариев в наши дни, так что вот:

Можно было бы передать параметры функции следующим образом:

 // Here we call function 'myFunction' with the array of parameters.
$funcPrototype( $function_call_spec["parameters"] );
 

Однако я хочу правильно объявить «myFunction» с четкими аргументами и т. Д:

 function myFunction( $first_par, $second_par )
{

}
 

Затем следует вопрос: Существует ли какой — либо способ динамически передавать параметры функции, просто проходя по массиву параметров?

Чтобы уточнить, я не хочу делать это так:

 $funcPrototype( $function_call_spec["parameters"]["first_par"],
                $function_call_spec["parameters"]["second_par"]  );
 

Потому что для этого требуется, чтобы мой код статически знал подробности о моей функции, что противоречит всей идее.

Вместо этого я бы хотел сделать это каким-то образом, возможно, так:

 // Special magic PHP function which can be used for invoking functions dynamically
InvokeFunction( $funcPrototype, $function_call_spec["parameters"] );
 

Что затем приводит к вызову функции myFunction, и все параметры в массиве передаются каждой отдельной переменной параметра в прототипе.

Любые комментарии приветствуются.

С уважением.

/R

PS: Ни один код в этом посте не был протестирован на наличие опечаток и т.д.

Ответ №1:

Вы должны использовать call_user_func_array , который может вызывать любую функцию или метод и принимать параметры из массива.

В качестве альтернативы вы можете использовать ReflectionFunction::invokeArgs , но в этом нет никакой пользы call_user_func_array , если вы уже не используете этот класс для чего-то другого (например, для проверки того, принимает ли вызываемая вами функция соответствующее количество и типы аргументов).

Ответ №2:

 call_user_func_array($funcPrototype, $function_call_spec["parameters"]);
 

Возможно, вам захочется создать оболочку, которая назовет функцию в соответствии с вашими предпочтениями, например:

 function InvokeFunction($function, $args = array()) {
    return call_user_func_array($function, (array)$args);
}
 

С помощью этой функции вы можете вызвать ее 3 различными способами:

 $return = InvokeFunction('doStuff');
$return = InvokeFunction('doStuff', $single_arg);
$return = InvokeFunction('doStuff', $multiple_args);
 

Ответ №3:

call_user_func_array() это лучший выбор, если вам не нужно обеспечивать соблюдение контракта, в противном случае используйте ReflectionFunction .

Ответ №4:

http://us2.php.net/create_function

Когда вы используете create_function(), ваши аргументы не оцениваются до выполнения. Довольно мило.