I know Domain Models and Data Mappers are the OOP snob's choice (using 'snob' in a complementary way, as Martin Fowler calls himself one) - however, even Fowler says in POEAA that
"Active Record is a good choice for domain logic that isn't too complex..."
I have a simple product and invoice domain model, not too many tables/objects/concepts to model, and the relationships aren't that overly complex. So, is this a good use case for Active Record?
Fowler also states that Active Record is similar to the Row Data Gateway, the difference being that Active Record has domain logic.
Assuming this is a valid use case for Active Record, and since Zend provides Row Data Gateway, a solution of intelligent (as opposed to simply adding the table name) extending those objects seems like a good way to create Active Record objects using the Zend Framework. Indeed, that concept is discussed in this SO answer. Is this an acceptable way of implementing Active Record inside the Zend Framework?
Of course the most popular answer to that question is one by Bill Karwin (who worked on Zend's Db implementation), recommending not using Zend_Db_Table
or Zend_Db_Row
this way (at least that's how I read it).
I fully accept wanting to move to a Data Mapper solution if the domain model in question becomes more complex. I've looked at various ORM/DataMappers (for more than just the domain model in question, been reading more about OOP design patterns lately), and they really seem too much for some things.
I've done this and have been completely satisfied with the result.
IMO, the only thing you must never do is to use the parent methods in your controllers and views/view helpers. i.e. Always write your own methods in the extended Zend_Db_Table_Abstract and Zend_Db_Table_Abstract_Row classes that are used by the rest of your application. This will leave you option of swapping out your TDG/AR for something more complex if the need arises.
For something simple, then yes models extending Zend_Db_Table package is a fine choice. I've used it many times with great success, and it looks something like this:
class App_Model_Users extends Mojito_Model_Abstract
{
protected $_dbTableClass='App_Model_Users_Table';
public function getByEmail($email)
{
$Select=$this->_DbTable->select()->where(new Zend_Db_Expr('LOWER(usrEmail)=?'),strtolower($email));
$User=$this->_DbTable->fetchRow($Select);
return $this->verifyRow($User);
}
}
class App_Model_Users_Table extends Zend_Db_Table_Abstract
{
protected $_name = 'users';
protected $_primary = 'user_id';
protected $_rowsetClass = 'App_Model_Users_Rowset';
protected $_rowClass = 'App_Model_Users_Row';
}
class App_Model_Users_Rowset extends Zend_Db_Table_Rowset_Abstract
{
}
class App_Model_Users_Row extends Zend_Db_Table_Row_Abstract
{
protected function _insert()
{
// pre instert logic such as:
$this->password = sha1($this->password);
}
protected function _postInsert()
{
// email user a welcome
}
protected function _postDelete()
{
// delete related files such as avatar
// can also get a rowset of related many's to delete
}
}
You can read more here http://talentedmrjones.posterous.com/simple-models-with-zenddbtable
Of course you might not need or want all the functionality that I'm extending from Mojito_Model_Abstract, but I'm sure you get the gist of what's happening.