Question

class TopParent
{
    protected function foo()
    {
        $this->bar();
    }

    private function bar()
    {
       echo 'Bar';
    }
}

class MidParent extends TopParent
{
    protected function foo()
    {
        $this->midMethod();
        parent::foo();
    }

    public function midMethod()
    {
        echo 'Mid';
    }

    public function generalMethod()
    {
       echo 'General';
    }
}

Now the question is if I have a class, that extends MidParent because I need to call

class Target extends MidParent
{
    //How to override this method to return TopParent::foo(); ?
    protected function foo()
    {
    }
}

So I need to do this:

$mid = new MidParent();
$mid->foo(); // MidBar
$taget = new Target();
$target->generalMethod(); // General
$target->foo(); // Bar

UPDATE Top parent is ActiveRecord class, mid is my model object. I want to use model in yii ConsoleApplication. I use 'user' module in this model, and console app doesn't support this module. So I need to override method afterFind, where user module is called. So the Target class is the class that overrides some methods from model which uses some modules that console application doesn't support.

Was it helpful?

Solution 2

Directly - you can't. This is how OOP works.

You can do it by a little redesign, e.g. in MidParent add method:

protected function parentFoo()
{
    parent::foo();
}

and in Target:

public function foo()
{
    $this->parentFoo();
}

But, again, this is only a workaround to solve your question and not a solution.

OTHER TIPS

Try this (http://php.net/manual/en/language.oop5.final.php - not allow to overriding in the childrens):

final protected function foo()
{
    $this->midMethod();
    parent::foo();
}

in class MidParent and the class Target can't overrides this method.

Actually, you can do this like this way with Reflection::getParentClass():

class Foo
{
   public function test($x, $y)
   {
      echo(sprintf('I am test of Foo with %s, %s'.PHP_EOL, $x, $y));
   }
}

class Bar extends Foo
{
   public function test()
   {
      echo('I am test of Bar'.PHP_EOL);
      parent::test();
   }
}

class Baz extends Bar
{
   public function test()
   {
      $class = new ReflectionClass(get_class($this));
      return call_user_func_array(
         [$class->getParentClass()->getParentClass()->getName(), 'test'],
         func_get_args()
      );
   }
}

$obj = new Baz();
$obj->test('bee', 'feo'); //I am test of Foo with bee, feo 

-but this is an architecture smell in any case. If you need something like this, that should tell you: you're doing something wrong. I don't want to recommend anyone to use this way, but since it's possible - here it is.

@AnatoliyGusarov, your question is interesting and in a sense you can achieve what you desire using yii and php advances features like Traits and Traits in Yii.

Given that it depends on what version of php you are using.However in yii you can achieve this by behaviors and check this SOQ.

In a nutshell you have to use language advanced features or YII framework features to come around this kind of issues,but that boils down to actual requirements

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top