Home > Development, Zend Framework > Zend Framework Models – Part 1: Concepts

Zend Framework Models – Part 1: Concepts

February 22nd, 2010 Adrian Leave a comment Go to comments

The power in Zend Framework lies in its uncompromising flexibility. However, evidently, this also means its very difficult for new ZF users to pick up the framework and hit the ground running. The most common question I see is usually “where is the model?”. The goal of this post is to show some examples and hopefully some new ideas on how to tackle models. There is no one-size-fits-all solution folks. Let’s look at some options and some background…

The concept of a model

Before we can go any further, we must first figure out what a model is. This stuff isn’t an exact science, so there will be some gray areas. Much of this post is my opinion (read: not fact). This doesn’t necessarily make them right or wrong. I like to think I’m right, so feel free to argue with me in the comments below.

In an MVC application, the model is responsible for all the business logic. The controller should handle flow control (taking input, calling models, redirection, etc.), and the view is responsible for representing your application, usually with some sort of data language (XML, HTML, JSON, etc.)

Implementation and and interpretation of the pattern is up to the developer… there are some gray areas so don’t worry if it doesn’t meet the exact specification. However, one thing I like to practice is skinny controllers, fat models. By shifting a lot of the work to the models (and their underlying libraries) you can usually organize your application much better. The result is simpler and more organized (primarily better encapsulated) code.

Simply said, a model should contain your business logic. Any processing that revolves around your application data should probably be put into models. I consider a model to be anything that does something in the big picture of your application… things like reading/writing data, sending/receiving data, processing data. They do the “work”.

One mistake I see is people simply setting up ORM (ex: Doctrine) models for each of their tables and leaving it at that. Your models’ public interfaces should be very simple. I prefer to have their interface represent their actual domain logic. For example, if you are making a post, then your controller (or calling code) should simply call something very self explanatory like post->create( info ). One personal guideline I follow is not to have more than 4 or 5 parameters to a method, and ideally, only 1 to 3.

One common implementation of this annoyance of mine is putting in chained query calls in your controller. Yes, the actual database code is encapsulated, but you are still revealing way too much information in your controller. The whole point of them is to encapsulate not only the code, but also the underlying logic. This way, when your business logic changes, your controllers can usually continue to function properly.

Working with databases

Most web applications revolve around storing information in the database. Whether it’s posts, comments or pictures, it all boils down to the same few operations. You can call this CRUD: create, read, update and destroy. In practice, it’s often much more complicated… but they remain to be the underlying concepts for most database interaction.

Most other frameworks come with a default model class/component which is a huge push in the right direction. Zend keeps an open mind about it, providing a few tools to use if you want to work with the database. Zend comes with a huge Zend_Db component to handle your database operations. It also contains Zend_Db_Table which is an implementation of the Table Data Gateway and Row Data Gateway patterns.

Personally, I’m not a big fan of Zend_Db_Table. I still think Doctrine is much more powerful, though I do really like Zend_Db. It operates under some of the same principles as PDO (database abstraction layer), so if you have used that before, you will be at home. I also really like Zend_Db_Select, which is what the table classes use quite a bit.

Using a base model

Because there are so many different types of models, I don’t think there is much point in having a do-it-all base class. However, for the group of models that will need database access, I use something like this:

class Site_Model {
    protected $_db;

    public function __construct(Zend_Db_Adapter_Abstract $db) {
        $this->_db = $db;
    }
}

You can probably tell that the default model is not even needed… and that’s the point. However, depending on your needs, this is a good place to start adding some common functionality that your db models will need. You may want to also make them all loader or dependency injector friendly if your application requires that.

Zend_Db

Zend’s database abstraction layer is really nice to work with. If you use it in combination with Zend_Db_Select you can make the database end of your application very portable. Here are some common methods I use from Zend_Db:

query(string)

fetchOne(query)
fetchRow(query)
fetchAll(query)

insert(table, data)
update(table, data, where)
delete(table, where)

quote(value)
quoteInto(string, value)

Abstracting your queries

If I’m working on an application that I plan to release to the public, then I always use Zend_Db_Select. It works on the same concept as the above insert/update/delete methods, meaning that you never have to write any of the SQL. If you let the Db libraries do it, then you are able to get much more portable code. Zend_Db supports IBM’s DB2, MySQL, MSSQL, Oracle, PostgreSQL and SQLite, so Db_Select is targetted at the same databases.

The concept of Zend_Db_Select is that the query is an object, and you can add/modify different parts of it. This gives you a lot more flexibility over dynamic query creation, as well as the added bonus of portability.

Summary

For your basic database-oriented models, all you your class will need is access to the Zend_Db_Adapter_Abstract interface. Keep your public methods very domain-oriented and your controllers will thank you for it. Break out of the mindset that models = database tables, or even model = database. Usually only around half my models deal with database operations. ZF also has a ton of service libraries available to help with all the common social sites APIs out there.

The next installment of this post will go into some concrete examples and also some ideas on how to implement your models. Comments and criticism welcomed and appreciated as always. :)

  1. Luke
    February 22nd, 2010 at 11:01 | #1

    Aside form using Query Builder, which I think I might start using, this is exactly how I create my models. Although I usually do build a model around a table, though not around link tables.

  2. Adrian
    February 22nd, 2010 at 11:09 | #2

    Right on. I still only use Zend_Db_Select for about half my applications, depending on size and distribution goals. There are some other cool integration tricks you can use to really speed up your model development. I’ll go into them more on my next post.

  3. February 22nd, 2010 at 14:41 | #3

    Good write up. I would love to see how you integrate forms and models as well.

  4. February 23rd, 2010 at 01:02 | #4

    Hi Adrian,

    As you state “Comments and criticism welcomed and appreciated as always” here’s my thought on the subject.

    I am a little confused with your article. I myself have been looking for the ‘best’ way to go about models (as in php representation of underlying data layer). To me a model is a representation of let’s say a database table but in php, which to me means an object with properties as opposed to a row with attributes. For a Zend Framework module one would have several models which make up a domain model. For example all models that comprise a blog.

    This understanding is not just my idea, when looking at other ORM’s often this is how models are implemented. This implementation is often realized with a data mapper such as seen in the Zend Framework quick start tutorial (http://framework.zend.com/manual/en/learning.quickstart.intro.html)

    Now, as of version 1.10 looking at the quick start download all ‘buisiness logic ’ code has moved out of the model and is located in the data mapper class which delegates calls to the Table Data Gateway (Zend_Db_Table class) In this way you have thin models and models without any knowledge of underlying data layer. As for the controller, to me that is THE most logic place to talk to the data layer (mapper) to populate your models. Dealing with models this way you end up with three classes:

    - A table data gateway for all your database need s (queries and stuff)
    - A data mapper, to help you represent it in php
    - A model, as the representation in php for your views (html, xml, json,csv.. )

    I have created a code generator based on the latest quick start tutorial. To show what I mean you can download it at: http://www.sreknord.net/download/form/3. I have been using this setup in some projects and have yet to run into problems with it.

    As for the quick start, what I am talking about is not yet displayed in the tutorial but only in the related download at Zend. The tutorial still shows the ‘fat’ models with delegating calls such as fetchAll to the data mapper class.
    http://framework.zend.com/demos/ZendFrameworkQuickstart.zip

  5. Jurl
    February 23rd, 2010 at 01:14 | #5

    Great!! I was waiting for someone talking about Models and Best Practices with Zend Framework and PHP in general…

    It would be interesting to see how you handle object collections, if you use a ClassFinder aproach or you simply have a getAllModelsOfThisClass with a fetchAll inside your model (what doesn’t seem to clean to me…)

    Ah!! And how you avoid coupling between classes when you have a n to m object relationship too.

    Yep!! It looks like I need a real training thougt… :\

  6. hadean
    February 23rd, 2010 at 01:17 | #6

    And still another useful resource for my feedreader. Hail to the zftalk-buddys ;)
    Good ideas, well written, good article. Looking forward to the 2nd part.

  7. Adrian
    February 23rd, 2010 at 01:42 | #7

    Hey Leonard, thanks for your reply.

    The bottom line really is that there is no one single best way to handle the model layer. Everybody has their own taste, and projects have a huge range of requirements.

    I tend to focus on the domain logic quite literally. If the project is larger, then I might want to sacrifice the readability for something more concrete and consistent like the Zend_Db_Table libraries, or even Doctrine. My models sometimes even sit on top of those libraries.

    I think of the events that happen in our application, and how they trigger changes or request information from our application’s data. I use these to form the outmost interface to my models, which would interact with my controllers or CLI scripts. I’m not sure what the norm is with ZF models, but I have been keeping the class hierarchy going the same way the rest of Zend does.

    Model_User
    Model_User_Exception
    Model_User_Flags
    Model_User_Permissions
    Model_User_Row

    The controller would deal with Model_User, which may need to delegate some work to those other models. All my fetch methods return some sort of row or collection object (read-only).

    I’m not saying this is the best way to do it, but it’s what has worked for me. I haven’t given Zend_Db_Table much love since around 1.6, so I think I will revisit it to see how I like it again.

    Thanks for sharing your model generator code. When I get some time I’ll look over it and also Zend_Db_Table again and see what I think.

    One last thing I wanted to say – think of the models as a layer. It doesn’t matter of a specific model class is fat or not – it matters that the model (which isn’t limited to one class) actually encapsulates all of the actual business logic properly.

    Cheers

  8. February 23rd, 2010 at 02:24 | #8

    Hi Adrian,

    I do believe all roads lead to Rome. This just shows that the Zend Framework still needs to work on clarifying things and giving developers ‘best practice’ examples. As everybody has their own take on how to go about implementing/interpreting MVC. Also the term model is hard, it can mean so many things. As you define it -not limited to one class and as I see; as kind of a DTO (Data Transfer Object)

    But be sure to check out the generated code or the Zend quick start download, I myself almost gave up on Zend_Db and the setup with TDG, Mapper and Model classes but I now feel like I have found a way to go with good SOC (Separation Of Concerns)

    Cheers

  9. Frank Desmettre
    February 23rd, 2010 at 04:32 | #9

    Personally, I don’t agree with the way you are working. Yes, a small controller is a good thing, but putting all the business logic is a bad thing. I see a (domain) model more like the storage of an item (mostly getters and setters). I think you better place your business logic into a data mapper / gateway / service. You should use design patterns for what they are meant to be in my opinion. Anyway, nice article, it’s a start but should take notice of the comments in your article

  10. Adrian
    February 23rd, 2010 at 12:24 | #10

    I have used that pattern on several projects, but I seem to prefer to keep it simple unless the project requires something more substantial. I’ll try to include some examples of all these different approaches in part 2.

    Appreciate the feedback.

  11. February 24th, 2010 at 03:10 | #11

    awesome article, very simple yet effective introduction to Zend Framework (ZF)
    thanks

  1. February 22nd, 2010 at 11:01 | #1
  2. March 13th, 2010 at 07:04 | #2