开发者

Calling method X from each parent

开发者 https://www.devze.com 2023-04-07 09:58 出处:网络
what i\'m trying to do is call each method \"init\" from current class\'s parents. I\'m doing that to avoid programmers to have to call init method (parent::init()) each time they create an init meth

what i'm trying to do is call each method "init" from current class's parents.

I'm doing that to avoid programmers to have to call init method (parent::init()) each time they create an init method in a new controller.

Example:

class Aspic\Controller { } // main controller
class ControllerA extends Aspic\Controller { public function init() {/* do something 1 */}  
class ControllerB extends ControllerA {}
class ControllerC extends ControllerB { public function init() { /* do something 2 */ }
class ControllerD extends ControllerC {}

As you can see the init methods do not call parent init method but i want my app (there is an option) do it.

Thus when I'm loading ControllerD, before calling it's init method (there isn't in the example but the app test it), i want to call each parent init method.

sound like this:

parent::init(); // Controller C init
parent::parent::parent::init(); // Controller A init

So i did :

if($this->_autoCallParentsInit) {
    // Aspic\Controller is the main controller, which is the mother of all others
    $aspicControllerRc = new \ReflectionClass('Aspic\\Controller');
    $rc = new \ReflectionClass($this); // We are in D
    $currPrefix = '';

    // Calling each init methods of curre开发者_Python百科nt class parent
    // Avoid using parent::init() in each controller
    while(($parentClass = $rc->getParentClass()) AND $aspicControllerRc->isInstance($parentClass)) {
        /* 
        $aspicControllerRc->isInstance($parentClass)
        => because Aspic\Controller extends a "Base class". Thus, we stopped at Aspic\Controller
        */

        $currPrefix .= 'parent::';

        // Must have explicit method (not inherited from parent) BUT actually hasMethod does not care
        if($parentClass->hasMethod('init')) {
            call_user_func($currPrefix.'init');                     
        }
    }
}

This is not working because ReflectionClass::isInstance does not accept others argument than the object we want to test (and the not a ReflectionClass object representing it as in the example)

** Simply: I have an object $x, and i want to call the init method of each parent of the class of $x. **

Is it possible ?

I hope i was clear :)

Thanks


ControllerB has an init() method by virtue of extending ControllerA, so you shouldn't have to call parent::parent::init() to get to A's from C. You should be fine to call parent::init() from ControllerD, which will call ControllerC's init() method. If ControllerC calls parent::init() it will be calling ControllerA's init() method.

If you're trying to skip the Controller's specific init() code when being called by a subclass, you could add a flag function init($call_parent = false) and then, from lower controllers, call parent::init(true);


If you're not using the classes statically (which, from your code not stating static function, I assume you're not), have you tried using the __construct() method? It gets automatically called when you instantiate the class, for example:

class MyClass {
  public function __construct() {
    echo 'Hello!';
  }
}

$class = new MyClass();

That will automatically output 'Hello!', however if you extend the class and that child class contains a __construct() method you will have to put parent::__construct() inside the childs construct method, however you wont have to do it for every parent, just the once, for example:

class MyClassB extends MyClass {
  public function __construct() {
    parent::__construct();
    echo 'World!';
  }
}

class MyOtherClass extends MyClassB
  public function __construct() {
    parent::__construct();
    echo 'How\'s it going!';
  }
}

$class = new MyOtherClass();

That will output "Hello! World! How's it going!"

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号