Sable Foste的想法激發了我的靈感。
您可以使用其他參數指定的順序,然後使用variable variables:
function test($order, $_a, $_b, $_c){
$order = explode(';', $order);
${$order[0]} = $_a;
${$order[1]} = $_b;
${$order[2]} = $_c;
echo "a = $a; b = $b; c = $c<br>";
}
test('a;b;c', 'a', 'b', 'c');
test('b;a;c', 'b', 'a', 'c');
但嚴重的是,你爲什麼不能使用數組?這是最好的方式。
更新:我寫了這一點。我一定很無聊。
現在我覺得很髒。
class FuncCaller{
var $func;
var $order_wanted;
var $num_args_wanted;
function FuncCaller($func, $order){
$this->func = $func;
if(is_set($order)){
// First version: receives string declaring parameters
// We flip the order_wanted array so it maps name => index
$this->order_wanted = array_flip(explode(';', $order));
$this->num_args_wanted = count($this->order_wanted);
} else {
// Second version: we can do better, using reflection
$func_reflection = new ReflectionFunction($this->func);
$params = $func_reflection->getParameters();
$this->num_args_wanted = func_reflection->getNumberOfParameters();
$this->order_wanted = [];
foreach($params as $idx => $param_reflection){
$this->order_wanted[ $param_reflection->getName() ] = $idx;
}
}
}
function call(){
if(func_num_args() <= 1){
// Call without arguments
return $this->func();
}
else if(func_num_args() == $this->num_args_wanted){
// order argument not present. Assume order is same as func signature
$args = func_get_args();
return call_user_func_array($this->func, $args);
}
else {
// @TODO: verify correct arguments were given
$args_given = func_get_args();
$order_given = explode(';', array_shift($args_given));
$order_given = array_flip($order_given); // Map name to index
$args_for_call = array();
foreach($this->order_wanted as $param_name => $idx){
$idx_given = $order_given[$param_name];
$val = $args_given[ $idx_given ];
$args_for_call[$idx] = $val;
}
return call_user_func_array($this->func, $args_for_call);
}
}
// This should allow calling the FuncCaller object as a function,
// but it wasn't working for me for some reason
function __invoke(){
$args = func_get_args();
return call_user_func($this->call, $args);
}
}
// Let's create a function for testing:
function test($first, $second, $third){
$first = var_export($first , TRUE);
$second = var_export($second, TRUE);
$third = var_export($third , TRUE);
echo "Called test($first, $second, $third);<br>";
}
// Now we test the first version: order of arguments is specified
$caller = new FuncCaller(test, '1st;2nd;3rd');
$caller->call(1, 2, 3);
$caller->call('3rd;1st;2nd', 'c', 'a', 'b');
$caller->call('2nd;3rd;1st', 'Two', 'Three', 'One');
$caller->call('3rd;2nd;1st', 'Go!', 'Get Set...', 'Get Ready...');
echo "<br>";
// Now we test the second version: order of arguments is acquired by reflection
// Note we you won't be able to rename arguments this way, as we did above
$reflection_caller = new FuncCaller(test);
$reflection_caller->call(1, 2, 3);
$reflection_caller->call('third;first;second', 'c', 'a', 'b');
$reflection_caller->call('second;third;first', 'Two', 'Three', 'One');
$reflection_caller->call('third;second;first', 'Go!', 'Get Set...', 'Get Ready...');
簡短的回答是否 – kalpaitch
@kalpaitch - 好吧,symfony2做到了,所以有辦法。 – otporan
看看這裏的建議:http://stackoverflow.com/questions/4697705/php-function-overloading –