How to call grandparent method without getting E_STRICT error?

Sometimes I need to execute the grandparent method (that is, bypass the parent method), I know that this is the smell of the code, but sometimes I can not change other classes (frameworks, libraries, etc.).

In PHP, we can do something like:

call_user_func(array(get_parent_class(get_parent_class($childObject)), 'grandParentMethod')); 

The problem is that if you have E_STRICT errors, you will receive an error message:

Strict standards: the non-static method GrandParent :: grandParentMethod () should not be called statically ...

I found only one solution for this (without removing E_STRICT), and it just adds @ to suppress the error.

But what is really ugly, does anyone know a better solution?

Thanks! PS: I cannot create an instance of a new object, for example:

 $grandparent = get_parent_class(get_parent_class($son)); $gp= new $grandparent; $gp->grandParentMethod 

because I need to call my grandparents method in the context of $ son.

+11
inheritance php
source share
4 answers

You can use ReflectionMethod-> invoke ()

Example:

 <?php class Grandpa { protected $age = 'very old'; public function sayMyAge() { return 'sayMyAge() in Grandpa should be very old. ' . 'My age is: ' . $this->age; } } class Pa extends Grandpa { protected $age = 'less old'; public function sayMyAge() { return 'sayMyAge() in Pa should be less old. ' . 'My age is: ' . $this->age; } } class Son extends Pa { protected $age = 'younger'; public function sayMyAge() { return 'sayMyAge() in Son should be younger. ' . 'My age is: ' . $this->age; } } $son = new Son(); $reflectionMethod = new ReflectionMethod(get_parent_class(get_parent_class($son)), 'sayMyAge'); echo $reflectionMethod->invoke($son); // returns: // sayMyAge() in Grandpa should be very old. My age is: younger 

Note. The invoked method must be publicly accessible.

+2
source share

You can call the progenitor directly by name (you do not need either Reflection or call_user_func ).

 class Base { protected function getFoo() { return 'Base'; } } class Child extends Base { protected function getFoo() { return parent::getFoo() . ' Child'; } } class Grandchild extends Child { protected function getFoo() { return Base::getFoo() . ' Grandchild'; } } 

A call to Base::getFoo might look like a static call (due to the colon syntax :: :), but it is not. Just like parent:: not static.

Calling a method from the inheritance chain inside the class correctly binds the value of $this , calls it like a regular method, complies with the rules of visibility (for example, is protected) and is not a violation of any kind!

This may seem a little strange at first, but this is the way to do it in PHP.

+51
source share

You can use a separate internal method (for example, _doStuff to complement doStuff ) and call it directly from the grandson through the parent.

 // Base class that everything inherits class Grandpa { protected function _doStuff() { // grandpa logic echo 'grandpa '; } public function doStuff() { $this->_doStuff(); } } class Papa extends Grandpa { public function doStuff() { parent::doStuff(); echo 'papa '; } } class Kiddo extends Papa { public function doStuff() { // Calls _doStuff instead of doStuff parent::_doStuff(); echo 'kiddo'; } } $person = new Grandpa(); $person->doStuff(); echo "\n"; $person = new Papa(); $person->doStuff(); echo "\n"; $person = new Kiddo(); $person->doStuff(); 

shows

 grandpa grandpa papa grandpa kiddo 
+1
source share

Timo's answer works, but I think it works by chance more than design. If you look at the opcodes for $ this-> doX versus parent :: doX versus Grandparent :: doX, you will see that Grandparent :: doX is called as a static method, but PHP will use $ this, which is in scope

 $this->doX 17 1 EXT_STMT 2 INIT_METHOD_CALL 'doX' 3 EXT_FCALL_BEGIN 4 DO_FCALL 0 5 EXT_FCALL_END parent::doX 18 6 EXT_STMT 7 FETCH_CLASS 514 :1 8 INIT_STATIC_METHOD_CALL $1, 'doX' 9 EXT_FCALL_BEGIN 10 DO_FCALL 0 11 EXT_FCALL_END Grandparent::doX 19 12 EXT_STMT 13 INIT_STATIC_METHOD_CALL 'C1', 'doX' 14 EXT_FCALL_BEGIN 15 DO_FCALL 0 16 EXT_FCALL_END 

Because of this, the $ this parameter is available in grandfather's static call (from https://www.php.net/manual/en/language.oop5.basic.php ):

The pseudo-variable $ this is available when the method is called from the context of the object. $ is a reference to the calling object (usually it is the object to which the method belongs, but possibly another object if the method is called statically from the context of the secondary object). Starting with PHP 7.0.0, static invocation of a non-static method from an incompatible context results in $ this not being defined inside the method. Calling a non-static method statically from an incompatible context has been deprecated since PHP 5.6.0. Starting with PHP 7.0.0, a static call to a static method is usually not recommended (even if it is called from a compatible context). Prior to PHP 5.6.0, such calls already triggered a strict notification.

0
source share

All Articles