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.

Était-ce utile?

La 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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top