parent::parent in PHP
PhpOopParentPhp 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();
}
}