2017-10-20 105 views
1

我只想弄清楚我是否想使用存儲庫模式。 的三大優勢,我能找到:laravel放置模型而不是存儲庫的抽象

1. Testability (repositories can be injected into the controller) 
2. Abstraction (complex eloquent queries can be refactored into repository functions) 
3. Decoupling (enables me to replace the persistence layer) 

然而,除了3點我實在不明白它清楚。

1. I can just as well inject the model (or a mock for testing) 
2. I can also abstract the queries into functions and place them into the model instead of a repository. 

因此,假設我不關心與雄辯有關係,我真的沒有看到使用知識庫的觀點。我很欣賞任何改變主意的論點。

+1

如果您使用Eloquent,我建議您將所有數據相關邏輯放入模型中。如果你這樣做,你仍然遵循存儲庫模式,並使用存儲庫包有太多的缺點,並沒有給你任何真正重要的優勢。如果您使用的是查詢生成器或原始SQL查詢,請使用存儲庫包。 –

+0

Repository模式將幫助您將ORM作爲一個整體進行替換,並使用其他一些OM,如Doctrine。如果您通過注入雄辯模型類來創建存儲庫,將來可以用一些其他ORM替換雄辯的ORM。但是,如果你只是想把雄辯分解成一個額外的抽象,那麼它就毫無價值,而只是一種抽象。 – webDev

回答

0

從我的觀點和經驗來看,您可以使用Eloquent作爲您的存儲庫層。

對於點2,您可以創建範圍的方法,以便能夠與正常雄辯一起使用查詢

$users = User::whereHasACarOfColor('yellow')->where('active, true)->get(); 
// ... 
public function scopeWhereHasACarOfColor($query, $color) 
{ 
    return $this->whereHas(function ($cars) use ($color) { 

     return $cars->where('color', $color); 

    }); 
} 

我曾與庫層的不同經驗Laravel在過去的幾個月:

  1. 由於我想重新使用代碼,我不得不創建很多類似的方法,getUsersWithYellowCars()getUsersWithYellowCarsOrderedByName() ...
  2. 如果您決定不創建這麼多特定方法,那麼您將結束與一堆方法有很多的參數

    public function getUsersWithCars($color, $orderBy, $orderDescOrAsc, $paginate...) 
    
  3. 有時你需要的模型傳遞到倉庫,而不是與他們進行互動,直接與它交互的

    $students = $usersRepository->getStudentsForProfessor($professor, 'name', 'ASC'); 
    

    代替

    $students = $professor->getStudents()->orderBy('name')->get(); 
    
  4. 一段時間後如預期的代碼看起來不乾淨(檢查例3)

此外,如果您決定從MySQL更改爲SQLite,您不需要更改代碼上的任何內容,但是要說Eloquent已經是ORM。

0

讓我們打破你的好處之一清單按一個:

  1. 可測性(倉庫可以被注入控制器)

這是真實的。後來在你的問題中,你說你可以輕鬆地將一個模型注入到控制器中,所以有什麼意義?關鍵在於,如果使用接口來定義存儲庫方法,則可以在生產代碼中使用具體存儲庫來實際查詢雄辯模型,同時使用實現相同接口進行測試的「僞」存儲庫。我經常這樣做,我的「假」實現只是使用一個Collection來保存我正在測試的模型。這樣,您的測試運行得更快,您不必擔心控制器測試中的遷移。它還使您不必在單元測試中與數據庫進行交互。我並不是說它對數據庫進行測試本質上是不好的,但是你應該在可能的情況下避免它。使用存儲庫可幫助您加速測試,而不需要需要與數據庫進行交互。通過在您的控制器中鍵入存儲庫接口,您可以傳入一個假實現進行測試,並將服務提供程序中的實際實現綁定到您的生產代碼。

  • 抽象(複雜口才查詢可以被重構到存儲庫功能)
  • 這是取決於你。 Laravel中存儲庫模式的問題在於,無論您嘗試多麼努力,模型都與數據庫綁定。沒有辦法繞過它。您擴展應用程序並重新使用存儲庫的機會接近於零,因此這不一定是壞事。無論如何,業務邏輯不應該在您的模型存儲庫中,所以應用程序的核心(如果設計正確)仍然會從框架中抽象出來。在真實的存儲庫模式中,您的查詢是在存儲庫中定義的。但是由於Laravel的模型與數據庫緊密耦合,放置這​​個邏輯的位置並不重要。事實上,Laravel具有一些很好的雄辯功能,可能會使這種邏輯在您的模型中變得更直觀。在Laravel中,存儲庫的真正亮點就是我在第一點提出的,能夠在測試中從數據庫中進行一些抽象。

  • 解耦(使我更換持久層)
  • 這是存儲庫模式的主點和正是使得點#1可能。當然,傳遞Eloquent模型意味着無論模型在哪裏,數據庫也是如此。這只是你必須與Active Record共存的事情。


    擴大對@ Lloope的回答,另一個好處是已經在一個地方定義了複雜的查詢(無論是你的模型或倉庫),以避免這樣的代碼在你的代碼庫亂丟:

    $professor->getStudents()->orderBy('name')->get(); 
    

    ,而使用這樣的事情:

    $students = $usersRepository->getStudentsForProfessor($professor, 'name', 'ASC'); 
    

    與寫作各地您的應用程序雄辯查詢的問題是,隨着需求的變化,你必須更新這些查詢在您的應用程序中的任這可能只是在您的控制器中,或在您的應用程序的幾十個不同部分。一個存儲庫上的方法(或者甚至只是你的Eloquent模型)更容易維護。這意味着您的其他物體不需要擔心getStudentsForProfessor的功能或功能。他們只知道它會爲給定的教授返回一批學生。存儲庫可以幫助您在一個地方組織查詢邏輯。一旦你定義了這個界面,或者合同,你的其他對象可以依靠它來完成它所說的事情。隨着查詢需求的變化,您可以在一個地方更新實施,而不是在您的應用中全部更新。合同仍然是一樣的。這比在任何地方編寫雄辯的查詢都有更大的靈活性。

    +0

    我試圖用這個例子說的是,使用你的模型作爲存儲庫層,你可以放下它們的方法並直接使用它,所以在這個例子中,它是德教授誰擁有方法'getStudents',然後你可以訂購他們或分頁或其他。如果您在存儲庫上執行相同的操作,則應該創建'getStudentsForProfessor','getStudentsForProfessorOrdered','getStudentsForProfessorPaginated','getStudentsForProfessorOrderedAndPaginated'等。 – Lloople

    +1

    我看到了。那麼我會編輯我的答案。我爲我的誤會道歉 :) – samrap