star

胖胖 Model 的減重方法:Repository

開發application常常要對資料庫做各種不同條件的查詢。

這類的查詢code很容易到處重複。

以 Laravel Eloquent來說,controller很容易出現這樣的code:

這段「取出受歡迎的女性使用者」的code,在中小型application還可以接受,

一旦規模稍大就會在不同controller到處重複(duplicate)。

利用內建的query scope功能,雖然能夠稍微改善,但還是不夠:

不只如此,還會讓model裡面多出定義query scope的程式碼,導致model變胖:

這種時候,適合寫一個Repository進行封裝:

它會讓controller內的code簡潔、可讀許多:

如果您是 Laravel 使用者,這種搭配Automatic Resolution的寫法一定經常看到:

甚至可以寫一個共用的abstract class減少duplicate code:

透過Repository封裝還有一個好處:

測試controller或是service的時候可以抽換掉Repository,讓測試時不用碰到資料庫!

下次你的application包含大量query logic時,不妨試試看這個作法。

(Photo via Susanne Nilsson, CC licensed)

  • https://fmbase.tw/blog Yi-Ming Huang

    謝謝你的文章。

    在不同的 eloquents/models 之間有 relationship 的關係,認為會怎麼處理比較好?是每個 eloquent/model 都有一個 repository 還是可以視情況寫在一起?

    例如:user 有多個訂單,像是 User model 會與 Order model 有 1-n 關聯性,要查詢使用者的所有訂單、某段期間內的訂單等,使用 repository pattern 來 implement,這樣的情況會怎麼想比較合適?

    • 阿川先生

      都可以!寫在一起好理解就直接寫在一起,放哪個model都很怪就另開repository。我個人傾向多用repository。

      以您的範例來說,我會寫一個OrderRepository,
      寫個function getByPeriod($user, $start, $end);
      至於所有訂單則可直接運用Eloquent的hasMany。

      這樣您覺得OK嗎