One of my favorite design patterns is the Active Record pattern. For those of you who haven’t heard of it, this pattern abstracts database access to a very simplistic level. I first starting playing with my own implementations a couple years ago, but it wasn’t until I used Ruby on Rails that I first saw a fully functional implementation.
At Webmail.us, I have decided to use my side-project hours to work on my own version of the active record pattern. It has been a slow going process, since I rarely find free hours to work on it, but I have finally created a workable version. But, before we get to the inner workings of my implementation, I need to give credit where credit is due.
Rails Active Record:
Since the first active record pattern I encountered was the Rails implementation, I decided to start there with my first PHP implementation. It wasn’t long before I realized the PHP vs. Ruby differences were going to be a serious problem.
I wanted the find functions to be static, because an object shouldn’t have to populate itself after it has been instantiated. Unfortunately, in PHP, static methods aren’t capable of polymorphism (which makes sense since $this isn’t applicable). Therefore, overloading them becomes impossible.
CakePHP solved this by making all the find functions non-static, but I didn’t like this solution either, because it doesn’t make sense for the previously stated reasons. Then I found …..
The Zend framework, while still very new, has some powerful features, namely the DB section. When I first saw this implementation of the active record pattern, I knew this was the starting point for my own version.
Zend DB has three main classes, Zend_Db_Table, Zend_Db_Table_Row, and Zend_Db_Table_Rowset. This design is much more flexible, and makes more sense to me than Rails’ and CakePHP’s implementations. Each database object is abstracted to its own classes, aka tables, rows, and rowsets (or arrays of rows).
At first, I almost decided to use this implementation and forgo the long process of creating my own. But, it fell short of my requirements for a few different reasons. The biggest problem was that the Row and RowSet class names are hard-coded in the Table class. This means overloading them is impossible:
return new Zend_Db_Table_Row(array( 'db' => $this->_db, 'table' => $this, 'data' => $this->_fetch('Row', $where, $order, 1), ));
It also uses prepared statements, which I have never used and don’t really have a desire to. They are definitely slower than straight MySQL calls and I don’t have the mysqli extension installed so that is out (Although I should probably work on getting that extension installed).
Even though Rails, CakePHP, and Zend DB didn’t work out for me, they played in important role in leading me towards my current solution. In the future, I will discuss in more depth my own implementation and keep everyone updated with how it is working out.