Rails-like ActiveRecord for PHP 5.3

I’ve worked on a small project that makes Rails-like AciveRecord available for PHP 5.3. It’s unimaginatively enough called active-record-php. I think an approach of this nature would make a really viable competitor to the likes of Propel and Doctrine and I’ll tell you why!

It works exactly like Rails’ ActiveRecord. There are two features in PHP 5 which makes this possible (the magic function __call – equivalent to method_missing in Ruby) and something called late-static binding which is only available in PHP 5.3. __call allows dynamic method invocation and late-static binding (along with a few tricks) simulates class and instance methods in Ruby. Let’s see some code!


user.php:
<?php

require_once 'base.php';

class User extends ActiveRecord::Base {
  protected static $class = __CLASS__;

  public static $associations = array(
    'has_many' => array(
      'photos'
    )
  );
};

?>

photo.php:
<?php

require_once 'base.php';

class Photo extends ActiveRecord::Base {
  protected static $class = __CLASS__;


};
?>

That’s a basic has_many relationship. Include the base.php class (which lives in its own namespace), and that’s it. No more configuring schema.xml, regenerating boilerplate get/setter code, etc. It’s all in there.

How do you use it? Again, intuitive:


<?php

require_once 'user.php';
require_once 'photo.php';

ActiveRecord::Base::establish_connection(array(
  'host' => 'localhost',
  'database' => 'test',
  'username' => 'root',
  'password' => 'root'
));

$users = User::find_all();
$user = $users[0];
$user->user_name_set("Love");
$user->save();
print_r($user->photos());
print_r($user);

That’s all there to it. And less than 150 lines of code too!

Of course, this is more like a POC. The only stuff implemented are attribute getters and setters, a simple save(), a has_many relationship etc. No validation, the rest of the relationships, eager loading, et. al. But it’s easily doable. If somebody wants access to the github project do let me know! It does require PHP 5.3 though (which is currently alpha 2) but do give it a try: a siege benchmark showed 5.3 to be around 30% faster than 5.2.6 for a simple caffeine (note: that’s a link to my fork: the original is here) application, so 5.3 would be good!

Comments are welcome!

4 responses

  1. The more I see this kind of thing in PHP the more I realise that I should be using a different language. PHP is implementing all kinds of stuff like this that the majority of PHP users will never use (or understand). PHP developers want to build websites. Why wait for PHP to implement the features of these other languages when you can just go use the other language? Don’t get me wrong, I think this is more of a bug fix than a feature addition and was definitely a requirement. But to suddenly rush it because people want to implement a rail-like ORM layer … lame. Besides, AR is not the best pattern for ORM anyway. That’s why it’s near the front of those patterns in PoEAA. If they want to rush to implement something in a point release how about they work on namespaces? I am seriously tired of typing out long class names just because we might get a collision. PHP should do what it does best and just copy someone else’s work.

    Later.

    PS Good article though mate!

  2. Nice article. Thanks. 🙂 Eugene

  3. While I understand your reasoning for not doing so, it sure would be nice if there was backward compatibility for older releases of PHP… Unfortunately, few hosts maintain servers with the bleeding edge of PHP releases…

    Great work…

  4. Cool! 🙂 Inspired me enough to give 5.3 a try 😉

Leave a Reply

Create a website or blog at WordPress.com