如何使用call_user_func_array作为可选参数

时间:2013-12-06 00:21:13

标签: php oop reflection arguments optional

Class Base {
  function processAction($methodName, $params) {
    call_user_func_array(array($this,$methodName), $params);

  }
}

class Child1 extends Base {
  function getData($param1, $param2, $timestamp) {}
}

class Child2 extends Base {
  function getInfo($param1) {}
}

我将在processAction中调用以调用子类的方法。

我有多个具有不同方法签名的子类。我想将$ timestamp传递给其中一些。问题是,我不想让timestamp成为不需要的方法的可选参数。我希望能够将$ timestamp传递给相关方法。我该怎么做?

EDIT 我计划在cal_user_func_array()调用之前添加$ timestamp。

$array_push($params, $timestamp);

但这意味着,每个方法都会期望$ timestamp,这是我不想要的。

1 个答案:

答案 0 :(得分:4)

正如我的评论中所提到的,php只关心你传递足够的参数来匹配声明的参数数量。如果为参数设置默认值,那么它甚至不关心它。

该函数将“忽略”您传递给它的任何额外参数,因为php不关心并且不会抛出错误。但是,请注意,传递给函数的任何额外参数都是公开给函数。例如,无论实际声明了多少参数,您都可以使用func_get_args()来获取传递给函数的值数组。

示例1:

function myFunc() {}
myFunc(); // good
myfunc('foo'); // good

示例2:

function myFunc($p1) {}
myFunc(); // bad
myfunc('foo'); // good
myfunc('foo','bar'); // good

示例3:

function myFunc($p1='') {}
myFunc(); // good
myfunc('foo'); // good

示例4:

function myFunc() {
  print_r(func_get_args());
}
myFunc('foo','bar'); 
/*output:
Array
(
    [0] => foo
    [1] => bar
)
*/

现在让我们假设你做的事实和咧嘴笑,实际上你想要强制只将相关的args传递给方法。根据您最终想要做的事情,有几种方法可以强制执行此操作。如果要将其传递到传递命名参数的位置,则必须重新构建代码以接受params的关联数组。然后你可以编写一些条件来确定哪些条件被传递并传递它们或抛出异常或其他任何东西。如果你只关心参数的数量,它会更容易,因为你可以或多或少地保留你的代码结构,并计算传递的参数数量。

现在,只要弄清楚给定方法有多少参数。下面是一个使用Reflection类指向正确方向的示例:

Class Base {
  function processAction($methodName, $params) {

    // setup a reflection method object
    $refMeth = new ReflectionMethod(get_class($this).'::'.$methodName);

    // get a list of the parameter names, if you want to go the 'named' route
    foreach($refMeth->getParameters() as $param) {
      $sigParams[] = $param->getName();
    }

    // echo out as example
    print_r($sigParams);
    // or just get the number of params for the method
    echo $refMeth->getNumberOfParameters();

    call_user_func_array(array($this,$methodName), $params);

  }
}

class Child1 extends Base {
  function getData($param1, $param2, $timestamp) {}
}

class Child2 extends Base {
  function getInfo($param1) {}
}

// example:
$x = new Child1();
$x->processAction('getData',array('foo','bar','12345'));

/*output
Array
(
    [0] => param1
    [1] => param2
    [2] => timestamp
)
3
*/

所以有一个如何找出给定方法的预期参数的例子,所以你可以比较传递的args并显式调用只有相关值的call_user_func_array以便额外的(即使php会'忽略' '他们)甚至不会暴露,或者抛出异常,等等。