The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

Suggestions for my data model/ORM approach?

Hi all,

Apologies if what I'm about to mention has been discussed to death already, but I'm just having trouble getting my head around a design issue to do with my web apps. A bit of back story... a few years back I made my own framework in PHP4 (it was, perhaps mistakenly, similar in operation to Struts)... it was never released publicly and we used it in-house to create a wide range of sites, for which it worked well enough, despite some major performance tuning and optimisation (the number of things it was doing per R/R cycle was *ridiculous*, as was the number of object instances created)...

Anyway, these days I've pretty much abandoned it in favour of a very lightweight... uhh... I dunno if you'd even call it a framework; it's more of a set of mostly static classes with commonly-used functionality, config arrays, include() based templates with minimal scriptlet code for views, and the odd object instance here and there mixed with Page Controllers to run it all. It's pretty old school really, and while it has much, *much* room for improvement, it's quick and easy and works well for most sites we care to throw at it.

But I'll stop boring you with back story and now bore you with the issue at hand. It's to do with how I handle my "model" as such. What I've been doing currently (and this can change from project to project!) is structuring my model as classes much like this (let's use a blog for example - the code is not meant to be functional, it's more of an example of structure):

PHP Code:

class Record
{
/* some basic common Record functions as well as some abstract: */

Now, if you've got this far, here is my question: how much should I pull into memory as resolved objects? In this example, the BlogEntry has a BlogAuthor object associated with it, which in turn has an ID. When the record is saved, the "toDatabase()" function knows to return the $author->id as to create a foreign key for the DB operation. Vice versa, the "fromDatabase()" function does the opposite - it takes the obtained foreign key ID, and calls "BlogAuthor::FindById($id)" to obtain the object associated with this one.

I guess this is all simple ORM (object relational mapping)... but how far do you go with this? What if we have multiple objects (lists, collections) associated - do we pull all them in as well? What about objects associated with those objects? I guess Lazy Load could come into play here (like a good man, I do have PoEAA), but it's always confused me and I've wondered if it's overkill for PHP stuff.

So I guess what I'm asking is:

a) is this approach to model data sensible, or flawed?
b) should I be looking at implementing Lazy Load, and if so, what method is recommended (concerning 1:1 and 1:M relations)
c) because each PHP R/R cycle is so fleeting, should I be worried about model/data objects at all? Should I just be playing around with DB record arrays? Is it overkill?

I would love to hear the thoughts and opinions of those here who are much more intelligent and experienced than I. Oh and greetings from Canberra, AU - it's BLOODY cold here at the moment.

One approach I have used is to have something like an author_id field, which gets mapped to the object as an attribute using generic code which transforms the database row to the object which I have all models descend from (in your case, this looks like and ActiveRecord pattern, where I tend to favor a TableDataGateway myself). For the custom Model class, I might ad an author() function which would allow me to perform lazy loading of the author object and (since I am using php5 which supports method chaining) do things like:

One approach I have used is to have something like an author_id field, which gets mapped to the object as an attribute using generic code which transforms the database row to the object which I have all models descend from (in your case, this looks like and ActiveRecord pattern, where I tend to favor a TableDataGateway myself). For the custom Model class, I might ad an author() function which would allow me to perform lazy loading of the author object and (since I am using php5 which supports method chaining) do things like:

PHP Code:

echo $model->author()->full_name;

Hi, Jason... thanks for your reply... so what it looks like you're suggesting there is a lazy load implementation as such:

1. Hold a pointer (ID) to an object.
2. Always use a method to access the object, which first checks if it has been loaded or not...
3. If not, load the object from the DB, if so, just return the already obtained object.

Does that sound right? How about collections of objects? I remember PoEAA mentioning that collections should be considered carefully as you will want to grab a whole heap of objects at once using a single query rather than a query for each object in the collection.

Regarding TableDataGateway vs ActiveRecord, would you be able to post the reasons why you prefer TableDataGateway? I don't really have a preference at the moment, it just seems the stuff I've been doing resembles ActiveRecord, and I'd like to know of any advantages of the alternative patterns.

Hi, Jason... thanks for your reply... so what it looks like you're suggesting there is a lazy load implementation as such:

1. Hold a pointer (ID) to an object.
2. Always use a method to access the object, which first checks if it has been loaded or not...
3. If not, load the object from the DB, if so, just return the already obtained object.

Does that sound right?

With regards to #1, it is not a pointer, but rather just a piece of data which you can used with the "findById()" method of your finder object.

Originally Posted by {RainmakeR}

How about collections of objects? I remember PoEAA mentioning that collections should be considered carefully as you will want to grab a whole heap of objects at once using a single query rather than a query for each object in the collection.

In part, see my answer below regarding TableDataGateway vs ActiveRecord, but one additional thought here is inside of your Finder methods of your gateway object, you can implement a registry (called an IdentityMap as a design pattern) to hold instances of the objects of that type which you have already loaded. This can let you avoid reloading them from the database, and may allow you to intelligently query a result set from your database and populate a collection of your model objects.

Originally Posted by {RainmakeR}

Regarding TableDataGateway vs ActiveRecord, would you be able to post the reasons why you prefer TableDataGateway? I don't really have a preference at the moment, it just seems the stuff I've been doing resembles ActiveRecord, and I'd like to know of any advantages of the alternative patterns.

Cheers,

{R}

My web applications tend to be reporting applications, and as such tend to get results sets back composed of many rows rather than working with an individual row at a time (which would be more common with a transactional type of application). These two design patterns could be summarized as ActiveRecord is the simplest data access pattern focused on at the row level, and TableDataGateway is the simplest data access pattern focused at the result set level. Since my application tend to operate at the result set level, it is more natural for me to want to operate with a TableDataGateway in preference to the ActiveRecord pattern.