如何正确实施正确使用类方法?

时间:2009-10-19 16:26:45

标签: php oop orm

我们当前的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发出一个调用,它可以先搜索其缓存的对象,然后只调用数据库来加载记录(如果需要的话)。

2 个答案:

答案 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实例。

相关问题