Question

Suppose following situation. There are class hierarchy, that uses various arguments list in a method, that might be extended for each descendant class.

<?php
header('Content-Type: text/plain; charset=utf-8');

class A {
    public function __invoke(){
        $arguments = implode(', ', func_get_args());

        echo __METHOD__, ' arguments: ', $arguments, PHP_EOL;
    }
}

class B extends A {
    public function __invoke(){
        //               ... some actions ...
        // call to parent method with current argument list
        //               ... some actions ...
    }
}
?>

If this class hierarhy were implemented with fixed arguments of __invoke() method, then I might use something like parent::__invoke($a, $b, $c, $etc); to achieve my purpose. But, unfortunately both classes A and B has some functionality, that relies on various argument lists.

Now, the question: How can I call parent::__invoke() from B::__invoke() and pass it's arguments list?

And, yeah, I'll make it more complex: I can not rely on actual name of parent class, because chain might be extended further.

P.S.: I just want to mention this somewhere, because this thing is nearly saved my life today.

Was it helpful?

Solution

There are two ways to implement that, one of which is obvious to me: to use Reflection.

  1. Create a ReflectionClass from class A;

  2. Get reflection nearest parent with ReflectionClass::getParentClass() method;

  3. Get __invoke() method reflection of parent class by ReflectionClass::getMethod() method;

  4. Use ReflectionMethod::invokeArgs() method to call parent method with func_get_args() function to pass current argument list.

However, I'm thinking, that it might be an overkill (!) to use this functionality to make a single function call. So I'm considered another way: old and mighty call_user_func_array() function with get_parent_class() function.

  1. Get parent class with get_parent_class() function;

  2. Get current method name (I was thinking to use __METHOD__ constant, but it always showing a class prefix, where method is declared) with __FUNCTION__ constant;

  3. Call call_user_func_array() with method map and pass func_get_args() as the second argument.


Solution:

<?php
header('Content-Type: text/plain; charset=utf-8');

class A {
    public function __invoke(){
        $arguments = implode(', ', func_get_args());

        echo __METHOD__, ' arguments: ', $arguments, PHP_EOL;
    }
}

class B extends A {
    public function __invoke(){
        echo __METHOD__, ' actions', PHP_EOL;

        $method = array(get_parent_class($this), __FUNCTION__);
        $result = call_user_func_array($method, func_get_args());

        echo __METHOD__, ' actions', PHP_EOL;
    }
}

$test = new B();

$test(1, 2, 3);
?>

Result:

B::__invoke actions
A::__invoke arguments: 1, 2, 3
B::__invoke actions
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top