I'm trying to use get_called_class()
on a parent class, and retrieve the parent class name rather than the subclass name. I can't use __CLASS__
in this case because I need it in a dynamic context since these methods are actually being inserted into an existing class using Closure::bind
and __call
.
Quick example:
<?php
class Test {
function doSomething() {
echo(get_called_class() . ",");
}
}
class TestSuper extends Test {
function doSomething() {
echo(get_called_class() . ",");
parent::doSomething();
}
}
$test = new TestSuper();
$test->doSomething();
?>
This example prints TestSuper,TestSuper,
, but I want something other than get_called_class()
which dynamically gets the class where the method exists (printing TestSuper,Test,
) rather than the class which was called. It also must work inside the magic __call
method. Is this possible?
Update: Better example which more closely reflects what I'm doing: I have a list of methods which I want to apply to an instance (or class) at runtime (in the $addons
variable):
<?php
$addons = array(
"A" => array(
"doSomething" => function () { return 10; }
),
"B" => array(
"doSomething" => function () { return parent::doSomething() + 1; }
)
);
class A {
private $methods = array();
function __construct() {
global $addons;
$class = get_class($this);
do {
foreach ($addons[$class] as $name => $method) {
$this->methods[$class][$name] = Closure::bind($method, $this, $class);
}
$class = get_parent_class($class);
} while ($class !== false);
}
function __call($name, $arguments) {
$class = get_class($this); // Or something else...
do {
if (isset($this->methods[$class][$name])) {
return call_user_func_array($this->methods[$class][$name], $arguments);
}
$class = get_parent_class($class);
} while ($class !== false);
}
}
class B extends A {
}
$b = new B();
echo($b->doSomething() . "\n");
?>
I'm adding a method doSomething
to A
, and overriding it on B
, but there I want to call parent::doSomething()
which will execute A
's doSomething
. Unfortunately, when it comes to executing the parent method, I can't find a way to know that I want to run A
's method instead, so it always runs B
's and eventually runs out of stack frames. How can I know in the inner __call
method to execute the superclass method?
You can use
__CLASS__
in__call()
.In closures, just use
get_called_class
.Outputs:
Test,Test,TestSuper,TestSuper,