Wrapper function hack for call_user_func_array
which enables you to use keyword arguments on PHP functions and methods. It aims to be as close as possible to the behavior of call_user_func_array
.
<?php
/**
* @link http://l-x.github.io/blog/2014/09/29/call-user-func-struct/
*
* @param callback $function
* @param array $param_struct
*
* @return mixed
*/
function call_user_func_struct($function, array $param_struct) {
/**
* @param callback $function
*
* @return ReflectionFunction|ReflectionMethod
*/
$getReflection = function ($function) {
switch(true) {
case ($function instanceof \Closure):
case (is_string($function) && function_exists($function));
return new \ReflectionFunction($function);
break;
case (is_string($function) && strpos($function, '::') !== false):
$function = explode('::', $function, 2);
case (is_array($function) && count($function) == 2 && (is_object($function[0]) || is_string($function[0])) && is_string($function[1])):
return new \ReflectionMethod($function[0], $function[1]);
break;
default:
trigger_error(sprintf("call_user_func_array() expects parameter 1 to be a valid callback, function '%s' not found or invalid function name", print_r($function, true)), E_USER_WARNING);
exit;
break;
}
};
/**
* @param array $params
* @param \ReflectionParameter[] $reflection
*
* @return array
*/
$prepareArguments = function (array $params, array $reflection) {
$prepared_arguments = array();
foreach($reflection as $parameter) {
if(isset($params[$parameter->getName()])) {
$prepared_arguments[] = $params[$parameter->getName()];
} else if($parameter->isDefaultValueAvailable()) {
$prepared_arguments[] = $parameter->getDefaultValue();
} else {
trigger_error(sprintf("Missing argument %s ($%s) ", count($prepared_arguments) + 1, $parameter->getName()), E_USER_WARNING);
exit;
}
}
return $prepared_arguments;
};
return call_user_func_array($function, $prepareArguments($param_struct, $getReflection($function)->getParameters()));
}