Our current ORM solution uses Data Mappers to represent tables / views in the database which then return a Collection object that can be used to iterate through the retrieved records as Model objects. Between the Data Mapper and Model layers is a Repository layer that handles domain requests to the data mappers and returns the corresponding collections or domain objects.
We are currently looking at refactoring the responsibilities of the Repository and Data Mapper layers so that all application requests to the Data Mapper layer are routed through the Repository and the Data Mapper returns the retrieved data rows to the Repository which then returns the necessary collection to the requesting object.
What I'm wondering is whether it is valid / good practice to pass the entire Repository object into the corresponding Data Mapper so that we can enforce access to the Data Mappers only through the Repository layer.
As an example this is basically how it works now:
class DataMapper {
public function findAll(Criteria $criteria)
{
$select = $criteria->getSelect();
// Build specific select statement
$rows = $this->_fetchAll($select);
return new Collection(array('data' => $rows, 'mapper' => get_class($this)));
}
}
I thinking of doing something like this:
class Repository {
public function findAllByName(Model $model)
{
$this->_criteria->addCondition('name LIKE ?', $model->name);
$rows = $this->_mapper->findAll($this);
return new Collection(array('data' => $rows, 'repository' => get_class($this)));
}
}
class DataMapper {
public function findAll(Repository $repository)
{
$select = $repository->getCriteria()->getSelect();
// Build specific select statement
$rows = $this->_fetchAll($select);
return $rows;
}
}
And then in this version, the Collection object would issue a call to the Repository which could first search through its cached objects and then only issue a call to the database to load the record if its needed.