Fat Models and the Data Access Layer
There’s been some discussion recently on why active record:
I like the active record pattern, so I don’t think it sucks, but I do think it’s used a little out of context sometimes.
If you’re building a small lightweight app, then I think using your Data access layer as the M in MVC is a logical thing to do. It’s quick, it’s easy and you can extend either your active record in Rails, or extend your Table DataGateway in the Zend Framework and you wont go far wrong.
As soon as your app gets a little more complex, you might want to start creating custom
models that contain more business logic than simply pulling and pushing to the database. If your application is complex enough, chances are your model will need to interact with more than one database table, if not database, so at this point, like Bill Karwin pointed out, your model should be using the DAL, not being the DAL. Loosening the coupling between model and DAL, should also help with automated testing the business logic, in that mock objects could replace the DAL.
The only problem is, I don’t know the best way to do it.
I’m currently learning the ways of the Zend Framework and would be interested to see how people think the best way to implement this kind of complex model. I’m currently leaning toward something like this. I’ve included a Zend_Form object, to show how the Persons model encapsulates more logic than just pushing to and from the database. I think the biggest benefit of Zend_Form is validating input, which I consider domain logic, so should be part of the model. But I’m not sure the best way to make things easily testable, without pushing into the realms of fancy Dependency Injection and what not, which I’m not all that familiar with.
File: application/models/Persons.php
<?php
class Persons
{
public function findByEmail($email)
{
$table = self::getTable();
$select = $table->select()
->where('email = ?', $email);
return $table->fetchAll($select);
}
public static function getTable()
{
// add some dependency injection?
return new Persons_Table();
}
public static function getForm()
{
// add some dependency injection?
return new Persons_Form();
}
// ...
}
File: application/models/Persons/Table.php
<?php
class Persons_Table extends Zend_Db_Table
{
protected $_name = 'persons';
// ...
}
File: application/models/Persons/Form.php
<?php
class Persons_Form extends Zend_Form
{
// ...
}
At first it may seem that the Persons model just ends up acting as a proxy to the Persons_Form and Persons_Table, but once you start writing methods that use both together, you’ll start seeing fatter models and thin controllers, which is all good.
This really is a request for comments really, as I’m personally not sure about the best way to go about this. Would be interesting if any of the people using the MVC part of the Zend Framework in the real world go about this?
Tags: ActiveRecord, MVC, Patterns, PHP, zend framework








June 21st, 2008 at 7:34 am
I think you’re on the right track with this approach. I’ve been trying to make models fatter with ZF recently, but it had not occurred to me to consider Zend_Form to be part of the model. I like it a lot.
It seems there are a whole bunch of alternative implementations available to you, though. Persons could extend an abstract class with default definitions of getTable and getForm, instead of being static methods of Persons. That abstract class could use the same kind of path magic that Zend_Loader uses, or you could just stick to your filename convention; using the __CLASS__ magic constant for the directory name.
That’s just off the top of my head… I don’t know if this fits smoothly in to your TDD routine. My head always hurts after reading Fowler (always worth it, though).
Can’t wait to see more comments on this. Good post.
June 21st, 2008 at 10:49 am
Thanks demon, an abstract Model class could definitely provide the basic getForm and getTable methods, would save implementing them repeatedly, seeing as we’d probably want to do Organisation::getTable() from the Person Model for example.
I had a quick look at Zend_Di, which looks like a nice simple solution to the Dependency Injection.
I wouldn’t hold your breath for more comments, this blogs not popular enough ;)
June 23rd, 2008 at 9:31 am
There isn’t really common practise for this. In cases like this I ask myself:
1. How reusable is this package iam creating? Is abstracting it really worth the effort and if iam going to absctract how abstract would it need to be to be reusable?
2. Enviorment, in the context of your example its realy the duty of the controller to couple both models together. Hence all the methods described in the linked article Dependency Injection can be applied. But wich solution all depends on rule 1.
June 23rd, 2008 at 12:34 pm
If you guys come to implement some more on this “new/divided” Model, please publish it here. I’m very curious about this ideas.
I think it’s hard to foreseen if a class will be reusable or not, I’m mean, will be “need” in another process or not, so I always try to loose the coupling the most I can.
So to me, having this new layer is very cheap and worths the price, always. It’s cleaner and gives back to Model it’s actual role, that is take care of the logic, the “information”, and let the TableGateway take care of the “data”.
June 23rd, 2008 at 1:43 pm
Hi Dave,
Aside from what seems to be questioning a gut feeling, you don’t really specify any particular issue with what you’re doing so maybe what you’re after is some additional justification…
First you could mention the added flavour that a row class would bring to this mix:
// in your table class
protected $_name = ‘persons’;
protected $_rowClass = ‘Persons_Row’;
class Content_Row extends Zend_Db_Table_Row_Abstract implements Some_Cool_Class
{
protected function _insert()
{
if(is_null($this->date_created)) {
$this->date_created = date(’Y-m-d H:i:s’);
}
}
}
Then that your persons class is now freer to subclass something like say an observer pattern class:
class Persons extends Something implements Something_Else …
Finally (since it’s too late for anything else to spring to mind rather than this being a grand reason) I’ll wave my hand and say I’ve been taking this approach. I’ve not however had the form tied so tightly though I do like the idea.
Fat Model, skinny controller in a flexible more easily testable package; looks good.
January 11th, 2009 at 2:24 pm
[...] Dave Marshall: Fat Models and the Data Access Layer [...]
March 7th, 2009 at 1:48 pm
A good post and something I’ve been questioning myself lately. I’ve been pointed in the direction of ORM but there’s no good pre-existing Zend solutions available.
One thing that springs to mind here is that by extending Zend_Form you are substituting Zend_DB’s fluff with Zend_Forms in your ‘object’ class. So really the coupling moves from Zend_DB to Zend_Form.
Definitely an interesting substitution though, food for thought! :)
Has anyone found/come up with any other good solutions in the interim?
March 7th, 2009 at 6:34 pm
@matt Check out Matthew Weier O’Phinney’s post on Model Infrastructure
April 9th, 2009 at 4:01 pm
[...] Fat Models and the Data Access Layer | DaveDevelopment (tags: php zend zendframework) [...]
April 20th, 2009 at 4:30 pm
[...] No API! It would be really nice to have an API and there’s one in the works, but it’s sounds like it’s a bit of a ballache changing fat controllers into fat models. [...]