parent::parent in PHP

PhpOopParent

Php Problem Overview


I search a way to access to the parent, parent function of a class without to call the parent... Hmmm, that sound a bit weird explanation so i will give an example:

class myclass
{
  public function test() { return 'level 1'; }
}
class myclass2 extends myclass
{
  public function test() { return parent::test() . '-level 2'; }
}
class myclass3 extends myclass2
{
  public function test() { return parent::test() . '-level 3'; }
}
$example = new myclass3();
echo $example->test(); // should display "level 1-level 2-level 3"

I would like to display "level 1-level 3" then doing something like that:

class myclass3 extends myclass2
{
  public function test() { return parent::parent::test() . '-level 3'; }
}

Do you have an idea how I can do this? (I am not allow to edit myclass and myclass2, they are part of a framework...)

Php Solutions


Solution 1 - Php

Simple solution. Use the root object myclass directly:

class myclass3 extends myclass2
{
  public function test() { return myclass::test() . '-level 3'; }
}

If you need a more general approach have a look at outis answer.

Solution 2 - Php

You could do it using get_parent_class

function get_grandparent_class($thing) {
    if (is_object($thing)) {
        $thing = get_class($thing);
    }
    return get_parent_class(get_parent_class($thing));
}

class myclass3 extends myclass2 {
    public function test() {
      $grandparent = get_grandparent_class($this);
      return $grandparent::test() . '-level 3'; 
    }
}

Or you could use reflection:

function get_grandparent_class($thing) {
    if (is_object($thing)) {
        $thing = get_class($thing);
    }
    $class = new ReflectionClass($thing);
    return $class->getParentClass()->getParentClass()->getName();
}

However, it may not be a good idea, depending on what you're trying to achieve.

Solution 3 - Php

No, this is not possible. Unfortunately there is no possibility to refer directly to the original class, only to it's self or to it's parent.

Solution 4 - Php

Maybe you can just add myclass2 as a member object in myclass3 and try to code like :

class myclass3{
myclass2 obj2;
public function test() { return $obj2->callParentTest() . '-level3';}
}

Solution 5 - Php

You cannot chain parents, instead create some sort of GetParent() method in your parent classes that simply returns $this;

Solution 6 - Php

if you want use the test function directly on class1 you must extend from class1. Please search about polimorphism.

will you try "parent::parent::parent::parent" when you have class5 ??

I think you can add a level parameter to test method. and check it first.

<?php
    class myclass
    {
        public function test($level) 
        { 
            return 'level 1'; 
        }
    }
    class myclass2 extends myclass
    {
        public function test($level) 
        { 
            
            return $level >= 2 ? parent::test($level) . '-level 2' : parent::test($level); 
        }
    }
    class myclass3 extends myclass2
    {
        public function test() 
        { 
            return parent::test(1) . '-level 3';
        }
    }
    $example = new myclass3();
    echo $example->test(); // should display "level 1-level 3"

Solution 7 - Php

There is no operator to get the root object. I would do something like this:

class myclass
{
  public function getRoot() { return __CLASS__; }
  public function test() { return 'level 1'; }
}
class myclass2 extends myclass
{
  public function getRoot() { return parent::getRoot(); }
}
class myclass3 extends myclass2
{
  public function getRoot() { return parent::getRoot(); }
  public function test() {
    $grandparent = self::getRoot();
    return $grandparent::test() . '-level 3';
  }
}
$example = new myclass3();
echo $example->test(); // should display "level 1-level 2-level 3"

Solution 8 - Php

In some situations, probably you can entirely override the root's method. I mean, instead of calling the parent's parent's one, you can copy the parent's parent's method code and add yours.

Solution 9 - Php

my approach: if you have the code:

class A {
	protected function method () {
		var_dump('A -> method');
	}
}

class B extends A {
	protected function method () {
		var_dump('B -> method');
	}
}

class C extends B {
	protected function method () {
		var_dump('C -> method');
	}
}

and you want in class C call method from class A (but not class B) refactor it to the code:

<?php

class A {
	protected function method () {
		$this->methodA();
	}

	protected function methodA () {
		var_dump('A -> method');
	}
}

class B extends A {
	protected function method () {
		var_dump('B -> method');
	}
}

class C extends B {
	protected function method () {
		$this->methodA();
	}
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlexandreView Question on Stackoverflow
Solution 1 - PhpPiTheNumberView Answer on Stackoverflow
Solution 2 - PhpoutisView Answer on Stackoverflow
Solution 3 - PhpWesley van OpdorpView Answer on Stackoverflow
Solution 4 - PhpLostMohicanView Answer on Stackoverflow
Solution 5 - PhpEric HerlitzView Answer on Stackoverflow
Solution 6 - PhpTufan Barış YıldırımView Answer on Stackoverflow
Solution 7 - PhpPiTheNumberView Answer on Stackoverflow
Solution 8 - PhpLuca ReghellinView Answer on Stackoverflow
Solution 9 - PhpMarek WoźniakView Answer on Stackoverflow