Question

For example:

I have a User which has 10 Widgets. Along with that I have a Manager that manages 5 of those widgets.

I want to retrieve the User's Widgets managed by a specified Manager. So I created a function in my WidgetMapper called fetchUsersManagedWidgets($userId, $managerId) which queries the db for those 5 widgets and maps an array of Widget objects.

I know domain objects are not supposed to be aware of their mappers, but can I create a function in the User model which calls a function of the WidgetMapper?

e.g.

class Application_Model_User {

    public function getWidgetsManagedBy($manager) {
        $widgetMapper = new Application_Model_WidgetMapper;
        return $widgetMapper->fetchUsersManagedWidgets($this->getId(), $manager->getId());
    }

}

Or is this a one way street, and domain objects should never call mapper functions?

Was it helpful?

Solution

Pattern in general are an idea of how you could solve a common problem. Their is neither a "have to do it that way" or "everything else is bad". In fact there's even a name for a decission not following patterns intentional.
From what I have seen people tend to think "one db-table is one domain so every db-table needs one model and one mapper". In your case i suppose you have three tables: users, widgets and the table holding the n:m relation between those two (i'll call it userwidgets).
The userwidgets is really part of the user-model and doesn't have a own model/mapper and is not part of the widget model. To resolve those widget ids in the usermodel do need the widget mapper of course which results in the problem you describe.
There are probably lot's of ways to resolve this, i simply assume a default-mapper which is overwritable:

Class UserModel
{
    $_widgetMapper = null;

    public function getWidgetMapper()
    {
        if(null === $this->_widgetMapper)
        {
             $this->setWidgetMapper(new DefaultWidgetMapper());
        }
        return $this->_widgetMapper();
    }

    public function setWidgetMapper($mapper)
    {
        // todo: make sure it's a mapper of the correct type
        $this->_widgetMapper = $mapper;
    }
}

In case you don't want to use the default widget-mapper you simply should set it before accessing the user's widgets (they should be loaded on demand).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top