Python 很棒的一點是它能夠使用名字將參數傳遞到一個函數,看起來是這樣的:
my_foo_function(param_name="value", another_param_name="another value")
今天我想在 PHP 5.4 中做同樣的事情(可輕鬆移植到 PHP 5.3),我寫了一個 call_user_func_named 函數,類似 PHP 內建的 call_user_func_array 函數,代碼如下:
<?php
$x = function($bar, $foo="9") {
echo $foo, $bar, "\n";
};
class MissingArgumentException extends Exception {
}
function call_user_func_named_array($method, $arr){
$ref = new ReflectionFunction($method);
$params = [];
foreach( $ref->getParameters() as $p ){
if( $p->isOptional() ){
if( isset($arr[$p->name]) ){
$params[] = $arr[$p->name];
}else{
$params[] = $p->getDefaultValue();
}
}else if( isset($arr[$p->name]) ){
$params[] = $arr[$p->name];
}else{
throw new MissingArgumentException("Missing parameter $p->name");
}
}
return $ref->invokeArgs( $params );
}
call_user_func_named_array($x, ['foo' => 'hello ', 'bar' => 'world']); //Pass all parameterss
call_user_func_named_array($x, ['bar' => 'world']); //Only pass one parameter
call_user_func_named_array($x, []); //Will throw exception
更新:很感謝一些熱心的貢獻者做的一些改進:
<?php
$x = function($bar, $foo="9") {
echo $foo, $bar, "\n";
};
class MissingArgumentException extends Exception {
}
function call_user_func_named_array($method, $arr){
$ref = new ReflectionFunction($method);
$params = [];
foreach( $ref->getParameters() as $p ){
if (!$p->isOptional() and !isset($arr[$p->name])) throw new MissingArgumentException("Missing parameter $p->name");
if (!isset($arr[$p->name])) $params[] = $p->getDefaultValue();
else $params[] = $arr[$p->name];
}
return $ref->invokeArgs( $params );
}
function make_named_array_function($func) {
return function($arr) use ($func) {
return call_user_func_named_array($func,$arr);
};
}
call_user_func_named_array($x, ['foo' => 'hello ', 'bar' => 'world']); //Pass all parameterss
call_user_func_named_array($x, ['bar' => 'world']); //Only pass one parameter
call_user_func_named_array($x, []); //Will throw exception
$y = make_named_array_function($x);
$y(['foo' => 'hello ', 'bar' => 'world']); //Pass all parameterss
$y(['bar' => 'world']); //Only pass one parameter
$y([]); //Will throw exception