php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #65828 parent::X() triggers child's __call('X'), instead of parent's __call('X')
Submitted: 2013-10-03 16:02 UTC Modified: 2013-10-04 16:15 UTC
From: stefaan at netlog dot com Assigned:
Status: Not a bug Package: Class/Object related
PHP Version: 5.4.20 OS: OSX, Ubuntu
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: stefaan at netlog dot com
New email:
PHP Version: OS:

 

 [2013-10-03 16:02 UTC] stefaan at netlog dot com
Description:
------------
In the code example below the parent::getX() call in BB::getX() resolves to CCC:__call('X') instead of to A:__call('X'), which I would expect.
It seems weird that "parent" in BB:getX() resolves to CCC, which is not the parent of BB (it's vice versa) nor CCC.


I get this behavior on PHP 5.3.26, but also PHP 5.4.20

Test script:
---------------
class A {
    public function whoami() { return 'A'; }
    public function __call($method, array $args) {
        return 'A::__call::' . $method;
    }
}
class BB extends A
{
    public function whoami() { return 'BB'; }
    public function getX() {
        return 'BB::getX (FYI: parent is ' . parent::whoami(). ') -> ' . parent::getX() ;
    }
}
class CCC extends BB {
    public function whoami() { return 'CCC'; }
    public function __call($method, array $args) {
        return 'CCC::__call::' . $method . ' -> ' . parent::__call($method, $args);
    }
}
$c = new CCC();
echo $c->getX() . "\n";


Expected result:
----------------
BB::getX (FYI: parent is A) -> A::__call::getX

Actual result:
--------------
BB::getX (FYI: parent is A) -> CCC::__call::getX -> A::__call::getX

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-10-03 17:46 UTC] rasmus@php.net
-Status: Open +Status: Not a bug
 [2013-10-03 17:46 UTC] rasmus@php.net
That's how classes are composed. There is no bug here. CCC:__call() is the active __call() method  for this instance no matter where in the hierarchy you are. You can explicitly call other versions of methods via lsb, of course. See http://php.net/lsb
 [2013-10-04 16:15 UTC] stefaan at netlog dot com
Thanks for the quick response.

So to get this straight, if I understood you correctly:
in BB::getX():
the call parent::getX() resolves to something like
"method A::getX() called on a CCC instance"
which does not exists and triggers
__call('getX') on the CCC instance, so CCC::__call('getX')


I'm not sure I understood your comment on LSB.
From the test script I learn that "parent::" is "non-LSB" like "self::", but there does not exist a LSB equivalent of "parent::", right? So there is no other option here. (And if there would be, it would result in an endless loop in this case.)
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Thu May 01 17:01:29 2025 UTC