PHP不提供这样的功能,但它可以在很大程度上被伪造。我刚写了这个东西。不是 100% 测试,但如果使用正确,它会工作。
如何使用它的示例:
call_user_func_args(function($a1, $a2, array $a3 = null, $a4 = null){
var_dump(func_get_args());
}, array(
'a1' => 1,
'a3' => null,
'a2' => 2,
));
// Output
array (size=3)
0 => int 1
1 => int 2
2 => null
它在类前面使用,因为它是用于PHP 5.3 或更高版本\
的命名空间代码。删除以尝试在 5.2 中使用它,但不能保证。\
这是代码:
/**
* Calls a function with named arguments.
* Just written and quite tested. If you find bugs, please provide feedback and I'll update the code.
* In a sane usage scenario, it will work. If you try your best, you might break it :)
* If true, $ValidateInput tries to warn you of issues with your Arguments, bad types, nulls where they should not be.
*
* @copyright Claudrian
* @param callable $Callable
* @param array $Arguments
* @param bool $ValidateInput
* @return mixed
*/
function call_user_func_args($Callable, array $Arguments, $ValidateInput = false){
// Make sure the $Callable is callable
if(!is_callable($Callable)){
trigger_error('$Callable is not a callable.', E_USER_WARNING);
return false;
}
// No arguments, no game
if(empty($Arguments)){
return call_user_func($Callable);
}
// Validate the input $Arguments
array_change_key_case($Arguments, CASE_LOWER);
foreach($Arguments as $ArgumentName => $ArgumentValue){
if(empty($ArgumentName) or is_numeric($ArgumentName)){
trigger_error('$Arguments cannot have numeric offsets.', E_USER_WARNING);
return false;
}
if(!preg_match('~^[a-z_][a-z0-9_]*$~', $ArgumentName)){
trigger_error('$Arguments contains illegal character offsets.', E_USER_WARNING);
return false;
}
}
// Get access to the function
try {
$Reflector = new \ReflectionFunction($Callable);
} catch(\Exception $Exception){
trigger_error($Exception->getMessage(), E_USER_WARNING);
return false;
}
// If function has not arguments, just call it but it's stupid
$RequiredParameterCount = $Reflector->getNumberOfRequiredParameters();
$ParameterCount = $Reflector->getNumberOfParameters();
if(!$ParameterCount){
return call_user_func($Callable);
}
// Prepare the $Parameters
$Parameters = array();
$PresetParameters = array();
foreach($Reflector->getParameters() as $Parameter){
$LowerName = strtolower($Name = $Parameter->getName());
$Argument = ($Available = array_key_exists($Name, $Arguments)) ? $Arguments[$Name] : null;
$Default = ($IsDefault = $Parameter->isDefaultValueAvailable()) ? $Parameter->getDefaultValue() : null;
$Parameters[$LowerName] = array(
'Name' => $Name,
'Offset' => $Parameter->getPosition(),
'Optional' => $Parameter->isOptional(),
'Nullable' => $Parameter->allowsNull(),
'Reference' => $Parameter->isPassedByReference(),
'Array' => $Parameter->isArray(),
'Defaultable' => $IsDefault,
'Default' => $Default,
'Available' => $Available,
'Provided' => $Available ? $Argument : $Default,
);
}
// Pop pointless nulls (from the last to the first)
end($Parameters);
while($Parameter = current($Parameters)){
if(!$Parameter['Nullable'] or !$Parameter['Optional'] or !is_null($Parameter['Provided'])){
break;
}
array_pop($Parameters); // Pop trailing null optional nullable arguments
prev($Parameters); // Move one back
}
// Prepare the final $Arguments
$Arguments = array();
foreach($Parameters as $Name => $Parameter){
if($ValidateInput){
if(is_null($Parameter['Provided']) and !$Parameter['Nullable']){
trigger_error("Argument '{$Name}' does not accept NULL.", E_USER_NOTICE);
}
if($Parameter['Array'] and !is_array($Parameter['Provided'])){
if(!$Parameter['Nullable'] and is_null($Parameter['Provided'])){
trigger_error("Argument '{$Name}' should be an array.", E_USER_NOTICE);
}
}
if(!$Parameter['Available'] and !$Parameter['Optional'] and !$Parameter['Defaultable']){
trigger_error("Argument '{$Name}' is not optional and not provided.", E_USER_NOTICE);
}
}
// Stoe this in the final $Arguments array
$Arguments[] = $Parameter['Provided'];
}
// Invoke the actual function
return $Reflector->invokeArgs($Arguments);
}