May 15, 2008

Zend Framework – An Example Model

Kevin Hallmark @ 3:48 pm —

Here is a little advice for people who want some guidance on creating their a model layer:

NOTE: This is merely a simple example, for guidance only. YMMV. There are a million different ways to do this kind of thing, this is merely one I have found effective.

In my apps, I generally create a BaseModel class, from which all others inherit. In this class, I’ll define a basic API that I want all models to subscribe to. This is usually something like __get, __set, setDataFromArray, validate (verify data is correct), filter (filter input data), save and other common methods.

This setup lets you change the backend storage mechanism easily. If all your model objects use the same API, you can change the underlying storage code of all your models simultaneously and your app is none-the-wiser.

An example:

Say I begin by using an array to store my data. Suddenly, I realize I want to store my data inside a database. I can change all the methods in my model to set data to a database object. Later in the project, I decide that XML would be a better choice. I can change my methods to write to an XML data file, and once again I don’t have to change my application code.

You can implement custom behavior by overriding methods and using the ‘parent’ keyword to call the BaseModel method implementation.

In most apps these days, my BaseModel class directly extends Zend_Db_Table_Row. Extending Zend_Db_Table_Row allows my model objects, with all their custom functionality, to be returned directly by Zend_Db_Table function calls. Creating lists is much faster when you don’t have to iterate the result set a second time to create model objects from them.

I usually won’t override the methods I want to use from Zend_Db_Table_Row (__get, __set, setDataFromArray). If I needed to change my storage engine I would implement these methods in my BaseModel to access the new data storage mechanism.

In each of my BaseModel subclasses, I’ll usually add some static getter methods.

For example:

Class User extends BaseModel {
Public static function getUser($user_id = null) {
//return a setup model object
$table = new users();//where users is your table class
If($user_id === null) {
$return = $table->createRow();
} else {
//get row from db
}

Return $return;
}

This function would return the model object for ‘$user_id’, or an empty object if null. You can call this method with

Each model then has a single point of origin. If I decide to change my implementation, I can be assured that “User::getUser” always will give me a fully qualified User object.

You can also create similar functions the will return a list of rows.

Hope this small bit of advice helps get your started.

2 Responses to “Zend Framework – An Example Model”

  1. Dumm Khan Says:

    I would go for inheriting my Base Model from Zend DB Table, this actually breaks the clean OO approach. Model and DAL should not have an IS-A relationship rather should have a HAS-A relationship.

  2. Kevin Hallmark Says:

    I need to upload my new BaseModel and write an article about it. For now though, I’ll address your point.

    By your logic, the “clean” OO approach should descend from neither the Row or the Table. The DAL should be completely independent. However, I ran into some problems with this approach.

    The reason I chose to descend it from Zend_Db_Table_Row because I generally want to interact with individual data objects, or collections there-in. I tried going through the clean OO approach originally, and it resulted in a lot of pass through code. It also broke record collections. In order to support collections coming from Zend, I ended up creating a lot of extra objects. Memory overhead was through the roof and the population algorithms got very expensive.

    Another factor is abstraction for the fetching of data objects. I don’t want to assume that my application will be database based in the future. If I switch to something else, like SOAP or REST based model population, then a Table is no longer relevant. The idea behind the static methods for fetching ONLY is that it abstracts out the retrieval of records and it directly associates them to the type of object produced.

    So, to summarize. I descend from the row, even though it isn’t as clean, because I want to utilize as much existing functionality from my DAL intact; the Zend Framework developers are better than I. Second, utilizing static accessors directly associates the fetch with the class/model it’s related to and it abstracts the fetch operation in case I decide to change my DAL in the future.

Leave a Reply

Logged in as . (Logout)