views:

404

answers:

1

Let's assume the following tables setup for a Zend Framework app.

user (id)
groups (id)
groups_users (id, user_id, group_id, join_date)

I took the Data Mapper approach to models which basically gives me:

  • Model_User, Model_UsersMapper, Model_DbTable_Users
  • Model_Group, Model_GroupsMapper, Model_DbTable_Groups
  • Model_GroupUser, Model_GroupsUsersMapper, Model_DbTable_GroupsUsers (for holding the relationships which can be seen as aentities; notice the "join_date" property)

I'm defining the _referenceMap in Model_DbTable_GroupsUsers:

protected $_referenceMap = array (
    'User' => array (
        'columns'       => array('user_id'),
        'refTableClass' => 'Model_DbTable_Users',
        'refColumns'    => array('id')
    ),
    'App' => array (
        'columns'       => array('group_id'),
        'refTableClass' => 'Model_DbTable_Groups',
        'refColumns'    => array('id')
    )
);

I'm having these design problems in mind:

1) The Model_Group only mirrors the fields in the groups table. How can I return a collection of groups a user is a member of and also the date the user joined that group for every group? If I just added the property to the domain object, then I'd have to let the group mapper know about it, wouldn't I?

2) Let's say I need to fetch the groups a user belongs to. Where should I put this logic? Model_UsersMapper or Model_GroupsUsersMapper?

I also want to make use of the referencing map (dependent tables) mechanism and probably use findManyToManyRowset or findDependentRowset, something like:

$result = $this->getDbTable()->find($userId);
$row = $result->current();

$groups = $row->findManyToManyRowset(
    'Model_DbTable_Groups',
    'Model_DbTable_GroupsUsers'
);

This would produce two queries when I could have just written it in a single query. I will place this in the Model_GroupsUsersMapper class.

An enhancement would be to add a getGroups method to the Model_User domain object which lazily loads the groups when needed by calling the appropriate method in the data mapper, which begs for the second question. Should I allow the domain object know about the data mapper?

+2  A: 

This can be pretty confusing issue because a relational database can be hard to map to an object model.

I'd be inclined to focus on your object model requirements first. For example if in your object model it makes sense for your user object to (almost) always be aware of the groups then this relationship should be incorporated into the user class. If on the other hand you often need to use users without needing to know what groups they are a part of perhaps you can have two user classes, a base class and a group aware extended version (base_user and group_user).

I would try to avoid letting the domain object know about the data layer as that's kind of the whole point to using this pattern. The data layer should pretty much just be a dumb factory that instantiates your domain objects.

Just my take on it :)

Jai
But how about retrieving a list of groups (just an array of Group objects so far) and the user count for each group as well? Should I return an array of arrays, where every small array has two properties - the Group object and the user count?
Seeker