Pragmatism in the real world

Active Record

I’ve recently been working through the PHP|Architect’s Guide to PHP Design Patterns and have decided to build my own version of an active record along the lines of the one in Ruby on Rails. It’s turning into an interesting experience as I’m doing using Test Driven Development methodology. This is proving very useful as I don’t really have a clue where I’m going with the design, and so having a series of tests for each step of the way is handy. Essentially I can refactor the internals as I work out that I’ve done it wrong and as long as the tests still pass, I know that I haven’t broken functionality that I have already done. This is incredibly liberating and I can see why adherents to TDD are so vocal about it.

I don’t think that my verison of Active Record will a seminal one. Certainly there are a good few out there and there will be one in the upcoming Zend Framework too. The one in the Zend Framework is especially interesting as the code samples given don’t appear to be valid in PHP! The details are in this post on Chris Shiflett’s blog. Essentially the interesting code is:

class Person extends ZActiveRecord {}     
 
$people = Person::findAll(array('nameFirst' => 'Daniel')); 
 
foreach ($people as $person) 
{ 
    echo $person->nameFirst . "n"; 
} 

It is clear that the findall() function must be defined in the class ZActiveRecord as we can see that it’s not defined in Person. However findall() is being called statically, which means that the function doesn’t know that a child class called it. So how does it know which table to select from?

My solution to this problem is to use a separate Finder class. Conceptually, my code will look like:

$finder = new ARFinder('Person');
$people = $finder->findAll(array('nameFirst' => 'Daniel'));
foreach ($people as $person) 
{ 
    echo $person->nameFirst . "n"; 
} 

The intention is that Finder::findall() will return a ARCollection which will allow for interation of the result set.

We’ll have to see how it goes when I’ve got tested code :)