3

I am implementing the Data Mapper design pattern in my Zend Framework web application, and everything goes well, I am really enjoying working with the data mapper in Zend and not applying only the Row Gateway pattern, but I am having a problem regarding my architecture. I am not sure how to reference and work with foreign key constraints in a OOP fashion with my data mapper. So I am having my Model class, my DbTable class and my Mapper class. Should I put all the foreign keys relations in my DbTable class and in this way I can retrieve in my mapper using findDependentRowset() function, or a better approach would be to instantiate the dependent class in my mapper. What is the best OOP practice in mapping foreign keys using the Data Mapper pattern?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Mythriel
  • 1,360
  • 5
  • 24
  • 45
  • If you have lots of Impedance Mismatch, consider using an ORM, like Doctrine2. – Gordon Oct 01 '11 at 11:17
  • I already started the project with the data mapper implementation, only problem I am having is handling foreign key mapping if either to instantiate objects or to let the DbTable be aware of the database schema – Mythriel Oct 01 '11 at 11:43
  • My implementation is something like this: Model - same as what you said, but without any functions, only setters and getter for accessing Model properties DbTable - no functions here, only subclassing Zend_Db_Table_Abstract and providing the id and name for the table DataMapper - does the meat - here I have all the functions and i retrieve the DbTable class and set the properties with the Model class I want my system to be as loose coupled as it can, so the problem is my foreign key relations in my application – Mythriel Oct 01 '11 at 11:49

2 Answers2

4

I'd go for the DataMapper as the other two shoudln't be aware of the ID per se althought it's always necessary for the relationship callers.

Model
- Property accessors and private property data holders
- Functions regarding correct usage of model
- Relatioship callers (calls relationship fetches in the DbTable to get parents or children rows)or returns cached data

DbTable
- Provides all static functions used to query data and instanciate the related Models such as :getById, getByName, getByComplexSearch, etc
- Provides all static relationship loaders such as: getParents, getChildrens and any other version you need

DataMapper
- Does the real meat and provides the getObjects method which accepts either a query part or a full query and loads the data into the ModelObjects and reads it back into a update, insert, delete query when needed
- Datamapper should be in charge of checking for relationship faults when inserting, updating or deleting using transactions if in InnoDB.

Does that make any sense?

Mathieu Dumoulin
  • 12,126
  • 7
  • 43
  • 71
2

I used to have findDependentRowset on my systems. But not anymore! It's a waste of resources in most cases. Table joins should be on your SQL statement.

See my answer here: Hand made queries vs findDependentRowset

I'm still far away from use Doctrine or Propel (I've never needed it). Maybe some day. (Now using Doctrine 2. So... I suggest you the same now)


OLD ANSWER

After a couple of years working with Zend Framework, I come across with the following architecture:

1) I have an abstract mapper which all my mappers extends: Zf_Model_DbTable_Mapper

2) I have an abstract model (domain object) too, similar to the Row Data Gateway, with the exception that it is not a gateway. It's a generic domain object: Zf_Model

3) When populating object graphs (SQL joins) one mapper delegates to the other mappers that are responsible for the given object.

Example

This method is from the abstract mapper:

    public function getById($id) 
    {


        $tableGateway = $this->getTable();

        $row = $tableGateway->fetchRow('id =' . (int) $id);

        if (!$row) 
            retur null;

        $row = $row->toArray();

        $objectName = $this->getDomainObjectName();
        $object = new $objectName($row['id']);
        $object->populate($row);

        return $object;    
    }
Community
  • 1
  • 1
Keyne Viana
  • 6,194
  • 2
  • 24
  • 55