sklar.com

...composed of an indefinite, perhaps infinite number of hexagonal galleries...

© 1994-2014. David Sklar. All rights reserved.

Runkit, "static", and inheritance

A 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”

Tagged with php , ideas