سؤال

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) {}
}

I will be calling in the processAction to call into the methods of the child classes.

I have multiple child classes with different method signatures. I want to pass in $timestamp to some of them. The issue is, I do not want to make timestamp an optional parameter for methods that do not require. I want to be able to pass in $timestamp to only relevant methods. How will i do that ?

EDIT I plan to add $timestamp just before cal_user_func_array() call.

$array_push($params, $timestamp);

But that would mean, that every method would expect $timestamp, which i don't want.

هل كانت مفيدة؟

المحلول

As mentioned in my comments, php only cares that you pass enough arguments to match the number of parameters declared. If you set a default value for a parameter, then it doesn't even care about that.

The function will "ignore" any extra parameters you pass to it, in the sense that php doesn't care and won't throw an error. However, note that any extra arguments passed to your function are exposed to the function. For example, you can use func_get_args() to get an array of values passed to the function, regardless of how many parameters were actually declared.

Example 1:

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

Example 2:

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

Example 3:

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

Example 4:

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

Now let's say for shits and grins you do in fact want to enforce only passing relevant args to the methods. There are several ways to enforce this, depending on what you ultimately want to do. If you want to make it to where named arguments are passed, you're going to have to restructure your code to accept an associative array of params. Then you can write some conditions to figure out which ones were passed and pass them along or throw an exception or whatever. If you only care about number of arguments, it will be easier, because you can more or less leave your code structure as-is, and count the number of params passed.

Now, as far as figuring out how many parameters a given method has. Here is an example using the Reflection class to point you in the right direction:

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
*/

So there's an example of how to find out the expected params for a given method, so you can compare to passed args and explicitly call call_user_func_array with only relevant values so that the extras (even though php would 'ignore' them) won't even be exposed, or throw an exception instead, etc..

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top