Runkit, "static", and inheritance
16 May 2007A PHP issue that comes up over and over again is how the static
keyword doesn’t know about inheritance. That is, code such as:
class Masons {
static $where = "World-wide";
static function show() {
print self::$where;
}
}
class Stonecutters extends Masons {
static $where = "Springfield";
}
Stonecutters::show();
prints World-wide
, not Springfield
because the self
inside Masons::show()
is bound at compile time to the Masons
class. This is different than how $this
works in instances, so it can be unexpected.
There are plenty of good reasons why PHP 5 works this way and it seems that in PHP 6 the static
keyword will be able to be used in place of self
to get the dynamic behavior a lot of folks are looking for (that is, print static::$where;
in Masons::show()
would cause Stonecutters::show()
to print Springfield
.
All well and good once PHP 6 is done.
In the meantime, I was noodling around with runkit and came up with some glue that lets you do something like this:
class Model {
public static function find($class, $filters) {
// This method would actually do an SQL query or
// REST request to retrieve data
print "I'm looking for a $class with ";
$tmp = array();
foreach ($filters as $k => $v) { $tmp[] = "$k=$v"; }
print implode(', ', $tmp);
print "\n";
}
public static function findById($class, $id) {
return self::find($class, array('id' => $id));
}
}
class Monkey extends Model { }
class Elephant extends Model {
public static function findByTrunkColor($color) {
return self::find(array('color' => $color));
}
}
And then after the mysterious (for a few seconds) glue:
MethodHelper::fixStaticMethods('Model');
you can do:
Monkey::find(array('name' => 'George', 'is' => 'curious'));
// prints: I'm looking for a Monkey with name=George, is=curious
Elephant::findById(1274);
// prints: I'm looking for a Elephant with id=1274
Elephant::findByTrunkColor('grey');
// prints: I'm looking for a Elephant with color=grey
Monkey::findById('abe');
// prints: I'm looking for a Monkey with id=abe
(The innards of MethodHelper
after the jump…)
Continue reading “Runkit, "static", and inheritance”