代码之家  ›  专栏  ›  技术社区  ›  Noah Goodrich

如何正确地强制使用类方法?

  •  0
  • Noah Goodrich  · 技术社区  · 15 年前

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

    我们目前正在研究重构存储库和数据映射器层的职责,以便所有到数据映射器层的应用程序请求都通过存储库路由,并且数据映射器将检索到的数据行返回到存储库,然后将必要的集合返回到请求对象。

    我想知道的是,将整个存储库对象传递到相应的数据映射器中,以便我们只能通过存储库层强制访问数据映射器,这是否是有效/良好的做法。

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

    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;
     }
    }
    

    然后在这个版本中,集合对象将向存储库发出一个调用,该调用可以首先搜索其缓存对象,然后仅在需要时对数据库发出一个调用,以加载记录。

    2 回复  |  直到 15 年前
        1
  •  1
  •   Koobz    15 年前

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

    它部分依赖于代码的上下文,但是依赖关系将存储库注入到您创建的数据映射器实例中,即:

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

    以后,只要您想使用findall(),就不用再传递$repo了。IE:

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

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

    如果您的存储库在上下文/实例之间有所不同,那么注入就更有意义了。如果您发现您总是在创建一个repo实例,并且希望回收它,那么使用单例可能是合适的。

    依赖注入的好处在于它确实澄清了这种依赖概念(讽刺!)。如果要强制执行它,可以执行如下操作:如果$repo对象为空,或者不是存储库实例,则在uConstruct()方法中引发异常。

        2
  •  1
  •   Chris Gutierrez    15 年前

    我可能会做得有点不同。我将添加setrepository(repository$repos)方法和getrepository()方法。然后,在findall方法中,调用getRepository()。如果尚未调用setrepository(),则getrepository可以返回默认的存储库实例。

    我还可能为知识库类创建一个接口,以便在datamapper类中使用不同的知识库实现。

    所以get方法看起来像

    public function getRepository()
    {
        if (!$this->_repository) {
            $this->_repository = new Repository();
        }
    
        return $this->_repository;
    }
    

    而set方法可能看起来像

    public function setRepository(RepositoryInterface $repos)
    {
        $this->_repository = $repos;
    }