The Nexus
Show navigation Hide navigation
  • BLOG
  • ABOUT
    • Ego Surfing
  • PROJECTS
    • n2
    • S2ajax
    • Condo
    • ezEdit
    • FreeBlog - Air
    • Tooredo Alpha
    • Tools
    • Journlr, Again!
26 Jul 2008 | 4 min. (718 words)

How I added real ActiveRecord support to adodb

Dead hard drive For my new projects, I have decided to use PHP5 , mostly because at least a couple projects will be worked on by a team and the learning curve is fairly forgiving.
I decided, however, to follow the model offered by Rails. I looked into a few PHP frameworks, such as Akelos, but realized that they were too constraining for our purpose. That’s when I decided to develop my own thin layer framework.

An excellent productivity tool is the ActiveRecord pattern. After all, it doesn’t matter what it is, that’s being mapped; whether it’s database tables or web services should not be relevant to the controller.
I have, in the past, used adodb successfully and I was happy when I realized that it comes with a ADOdb_Active_Record class.

Unfortunately, that class does a very basic job of mapping one class to a database table and that’s it. Therefore, support for has_many or belongs_to clauses.
I know that AR offers more features that those but I thought that these fit the very minimum requirement for them to be useful.
And that’s how I ended up modifying ADOdb_Active_Record to support these.

This article is mostly a series of listings that show the modifications-a bit- and how to use them-a bit more. First, here is how I am using them in my framework:
Let’s imagine a database that contains songs, artists and genres. Let’s look at the definition of a Song object:

belongsTo('artist');  
                $this->belongsTo('genre');  
        }  
}  
?>

and an Artist object:

hasMany('songs');  
        }  
}  
?>  

let’s have a look at a very basic controller that will allow us to retrieve our artists. Their songs will also be retrieved, since artists are defined as having many songs:

artists = &$artist->find(ALL, "artists.id=1", array('loading'=>ADODB_LAZY_AR));  
        }  
}  
?>  

Through the magic of my framework, which is outside the scope of this post, we will then be able to display our artists with their respective songs like so:

        {$artist->name}

";  
                foreach($artist->songs as $song)  
                {  
                        print "    TITLE:{$song->title}  
";  
                }  
        }  
        ?>

Note that, for this example, I removed as many irrelevant pieces of code as possible. For instance, we are always retrieving artist #1. The array that we are passing to the find() statement allows us to configure some of AR’s behaviours. In this example, we are passing ADODB_LAZY_AR, which is a hint that we do not wish to perform massive joins, but retrieve related objects on demand. If we wished to retrieve everything upfront, we could have used ADODB_JOIN_AR instead.

Now, our model classes are subclasses of ActiveRecord, which is another one of my framework classes, which provides a light abstraction on top of ADOdb_Active_Record. The relevant piece, for you, would be this one since we invoke it:

        function find($mode, $condition=null, $extra=array(), $bindArr=false, $pKeyArr=false)  
        {  
                // id?  
                if(ctype_digit($mode))  
                        return $this->load($mode);





                // return one row  
                if(FIRST == $mode)  
                        return parent::load($condition);





                // Assumption: ALL == $mode - return multiple rows  
                return parent::find($condition, $bindArr, $pKeyArr, $extra);  
        }  

It is interesting because the last line contains the actual call to ADOdb_Active_Record’s find() method.

In adodb itself, two files were modified: adodb-active-record.php and adodb.inc.php.

The former now contains two new structures: _hasMany and _belongsTo. ARs are now aware of the concept of foreign name, which is the name by which this object will be known to another object if a relationship is defined. This allows us, among other things, to naturally inflect tables names.

The latter was modified so that it accepts extra parameters, for instance in GetActiveRecordsClass(), and handle massive joins. Note that joins can be deferred through the use of ADODB_LAZY_AR. In which case I will use the model objects’ __get() method to load missing properties on-demand.

“Buyer Beware”
I hope to publish my full PHP framework in the near future; in the meantime, this hacked version of adodb has been very helpful in my work. I hope you too find it helpful. Beware, though: this is an early work and I would rather offer it to John Lim and let him integrate it in adodb-or can it if he’s too horrified!
I am aware of at least one bug, which may happen when using the join method on belongs_to objects. It could also do more things for you. Definitely not the cat’s meow.
But if you like it and need help, drop me a line.

[Download ](http://twitterified.com/file/get/adodb- ext-ar.zip “Download patched adodb files”)

Comments powered by Talkyard.

Twitterified…at last!

Current Obsessions, June ‘08

2022 The Nexus