我们当前的ORM解决方案使用数据映射器来表示数据库中的表/视图,然后返回一个Collection对象,该对象可用于将检索到的记录作为Model对象进行迭代。 Data Mapper和Model层之间是一个Repository层,它处理对数据映射器的域请求并返回相应的集合或域对象。
我们目前正在考虑重构Repository和Data Mapper层的职责,以便所有对Data Mapper层的应用程序请求都通过Repository进行路由,Data Mapper将检索到的数据行返回到Repository,然后Repository返回必要的收集到请求对象。
我想知道将整个Repository对象传递到相应的Data Mapper是否有效/良好做法,以便我们只能通过Repository层强制访问Data Mappers。
作为一个例子,这基本上就是它现在的运作方式:
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)));
}
}
我想做这样的事情:
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;
}
}
然后在这个版本中,Collection对象会向Repository发出一个调用,它可以先搜索其缓存的对象,然后只调用数据库来加载记录(如果需要的话)。
答案 0 :(得分:1)
我或许会这样做有点不同。我会添加一个setRepository(Repository $ repos)方法以及一个getRepository()方法。然后,在findAll方法中,调用getRepository()。如果尚未调用setRepository(),则getRepository可以返回默认存储库实例。
我也可能为Repository类创建一个接口,以便可以在DataMapper类中使用Repository的不同实现。
因此get方法看起来像
public function getRepository()
{
if (!$this->_repository) {
$this->_repository = new Repository();
}
return $this->_repository;
}
并且set方法看起来像
public function setRepository(RepositoryInterface $repos)
{
$this->_repository = $repos;
}
答案 1 :(得分:1)
克里斯有一个有效的建议。
它部分取决于代码的上下文,但依赖项将存储库注入您创建的DataMapper实例,即:
$repo = new Repository();
$mapper = new DataMapper($repo);
无论何时你想使用findAll(),都会让你不必再通过那个$ repo。 IE:
$mapper->findAll();
$mapper->findAllByName();
我发现当参数成为我正在进行的每个函数调用中无处不在的部分时,考虑将它们转换为实例变量是有意义的(特别是当它们每次都相同时)。
如果您的存储库因上下文/实例而异,则注入更有意义。如果您发现您总是创建一个repo实例并想要回收它,那么单例可能是合适的。
关于依赖注入的好处是它确实澄清了这种依赖性想法(具有讽刺意味!)。如果要强制执行它,可以在__construct()方法中执行类似操作,如果$ repo对象为null,或者不是Repository实例。