2009-10-19 128 views
0

我們當前的ORM解決方案使用數據映射器來表示數據庫中的表/視圖,然後返回一個Collection對象,該對象可用於遍歷檢索到的記錄作爲Model對象。 Data Mapper和Model層之間是一個Repository層,它處理對數據映射器的域請求並返回相應的集合或域對象。如何正確執行類方法的正確使用?

我們目前正在研究重構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; 
} 
} 

然後在這個版本中,集合對象會發出一個電話到存儲庫,它可以首先搜索它的緩存對象,然後只發出對數據庫的調用,以便在需要時加載記錄。

回答

1

克里斯有一個有效的建議。

這部分地取決於代碼的情況下,但依賴注入庫到您所創建的DataMapper的情況下,即:

$repo = new Repository(); 

$mapper = new DataMapper($repo); 

將隨後有,每當你想通過周圍是$回購饒你使用findAll()。 IE:

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

我發現,當參數成爲每一個函數調用我做的一個無處不在的一部分,這是有道理的考慮把他們變成實例變量(特別是當他們每次是相同的)。

如果您的存儲庫因上下文/實例不同而不同,那麼注入更有意義。如果你發現你總是創建一個回購實例並且想要回收它,那麼一個單例可能是合適的。

依賴注入的好處是它確實闡明瞭這種依賴性思想(具有諷刺意味!)。如果你想強制執行它,你可以在__construct()方法中做一些事情,如$ repo對象爲空或者不是Repository實例時拋出一個異常。

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

和設置方法可能看起來像

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