Emulating Ruby’s “super” in PHP
If you're new here, you may want to subscribe to my RSS feed. Thanks for visiting!
The code presented here is meant as a proof of concept and therefore does not have any error checking. Also, this is not meant to be used in production — it is merely a neat hack and should only be treated as such.
Following a discussion on FreeNode #php, where someone asked whether it was possible for a method M of class B, a subclass of class A to invoke something along the lines of Ruby’s super and call parent::M() — automagically.
It is, in fact, possible, but requires using an ugly hack — debug_backtrace().
So, here it is:
<?php
error_reporting(E_ALL);
class A {
public function super()
{
$bd = debug_backtrace();
$rc = new ReflectionClass($bd[1]['class']);
$pc = $rc->getParentClass()->newInstance();
call_user_func(array($pc, $bd[1]['function']));
}
public function foo() { printf(“omg, foo.\r\n”); }
}
class B extends A
{
public function foo()
{
printf(“zomg, B-foo.\r\n”);
self::super();
}
}
$b = new B();
$b->foo();
?>
Another version, without modifying classes can be done like this:
<?php
error_reporting(E_ALL);
function super()
{
$bd = debug_backtrace();
if (isset($bd[1]) && (isset($bd[1]['class']) || isset($bd[1]['object'])))
{
$cls = get_parent_class(isset($bd[1]['object'])?$bd[1]['object']:$bd[1]['class']);
$rm = new ReflectionMethod($cls, $bd[1]['function']);
if ($rm->isStatic())
$rm->invoke(NULL);
else {
$rc = new ReflectionClass($cls);
if ($rc->isInstantiable())
{
$rm->invoke($rc->newInstance());
}
}
}
}
class A
{
public static function foo() { printf(“zomg, a-foo.\r\n”); }
public function bar() { printf(“a-bar!\r\n”); }
}
class B extends A
{
public static function foo()
{
printf(“zomg, b-foo\r\n”);
super();
}
public function bar() { printf(“b-bar!~\r\n”); super(); }
}
$b = new B();
$b->foo();
$b->bar();
?>