【问题标题】:How to Properly Enforce Correct Usage of a Class Method?如何正确强制正确使用类方法?
【发布时间】:2009-10-19 16:26:45
【问题描述】:

我们当前的 ORM 解决方案使用数据映射器来表示数据库中的表/视图,然后返回一个 Collection 对象,该对象可用于将检索到的记录作为模型对象进行迭代。在数据映射器和模型层之间是一个存储库层,它处理对数据映射器的域请求并返回相应的集合或域对象。

我们目前正在考虑重构 Repository 和 Data Mapper 层的职责,以便所有应用程序对 Data Mapper 层的请求都通过 Repository 路由,Data Mapper 将检索到的数据行返回到 Repository,然后返回必要的集合到请求对象。

我想知道的是,将整个 Repository 对象传递到相应的 Data Mapper 是否是有效/良好的做法,以便我们只能通过 Repository 层强制访问 Data Mapper。

作为一个例子,这基本上是它现在的工作方式:

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 的调用,它可以首先搜索其缓存的对象,然后仅在需要时才向数据库发出调用以加载记录。

【问题讨论】:

    标签: php oop orm


    【解决方案1】:

    克里斯有一个有效的建议。

    它部分取决于代码的上下文,但依赖于将存储库注入到您创建的 DataMapper 实例中,即:

    $repo = new Repository();
    
    $mapper = new DataMapper($repo);
    

    将使您免于随后在您想使用 findAll() 时传递该 $repo。即:

    $mapper->findAll();
    $mapper->findAllByName();
    

    我发现当参数成为我进行的每个函数调用的普遍部分时,考虑将它们转换为实例变量是有意义的(尤其是当它们每次都相同时)。

    如果您的存储库因上下文/实例而异,则注入更有意义。如果您发现自己总是创建一个 repo 实例并希望回收它,那么单例可能是合适的。

    依赖注入的好处是它确实阐明了这种依赖的想法(讽刺!)。如果你想强制执行它,你可以在你的 __construct() 方法中如果 $repo 对象为空或不是 Repository 实例时抛出异常。

    【讨论】:

      【解决方案2】:

      我可能会做一些不同的事情。我会添加一个 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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-21
        • 2023-04-01
        • 2020-05-03
        • 1970-01-01
        • 1970-01-01
        • 2020-11-13
        • 2016-11-20
        • 2019-09-12
        相关资源
        最近更新 更多