(Notes:
- the code here has been taken directly from the PHP Late Static Binding documentation
- if you want a more verbose and thorough explanation of this problem, check this out
)
I have one thing to say for all of those PHP developers who look at Rails’ ActiveRecord class and get all excited about implementing it in PHP:
It can’t be done. Yet.
Here’s why:
Until PHP5.3, PHP does not implement a feature called “late static binding”. What is late static binding? Well, how about I show you what it’s like to NOT have late static binding:
class A { public static function who() { echo __CLASS__; } public static function test() { self::who(); } } class B extends A { public static function who() { echo __CLASS__; } } B::test(); //Outputs: 'A'
That’s right: B::test() outputs ‘A’. This is a problem, because while it is true that B is a subclass of A, B is still B. When I call a static method of B, I want it to know that it’s B.
With late static binding (only available in PHp5.3 and onward), this goes away:
<?php class A { public static function who() { echo __CLASS__; } public static function test() { static::who(); // Here comes Late Static Bindings } } class B extends A { public static function who() { echo __CLASS__; } } B::test(); //Outputs 'B' ?>
Why is this a problem for ActiveRecord? Well, say we define a class called ActiveRecord, and create a subclass of ActiveRecord called Person. When I call Person::find_all(), PHP5.2 is going to run find_all in ActiveRecord – and ActiveRecord’s find_all() will not know what kind of subclass I am. It won’t know if I’m a Person, Dog, Pizza, or any of that jazz. Essentially, ActiveRecord is now dead in the water.
Now, you could just make find_all a standard method instead of a static one, but then for every find operation, you’d have to do this:
$p = new Person(); $persons = $p->find_all();
Semantically, this doesn’t make much sense.
But, PHP coders, take heart – there are two silver linings:
- PHP5.3 has late static bindings! As soon as it’s released, rejoice, and implement ActiveRecord
- There’s always RowDataGateway!