什麼是Repository模式,如何使用Repository模式
這裡就不再囉嗦了,請參見以下幾個連結
如何使用 Repository 模式?
關於 Repository 的設計模式
laravel-china.org搜尋
我的使用歷程
原由
MVC
在如今仍然是流行趨勢,但多數框架都只提供基礎的MVC
架構。
幾年前在開發中我們經常會遇到問題Model
過於臃腫,寫著寫著就會變成類似於萬能類,最後面的人就真成了接盤俠了。
很不幸我就是其中之一。後來我就一直在思考如何才能讓Model
看起來清爽,功能更加單一簡潔。(當時並不知道Repository
),終於開始重構。一把心酸淚。。。。。最多的是組合和Trait
使用Laravel
最開始接觸Laravel就是感覺它的文件清爽,以為是個簡單的框架,結果不小心一入坑,才發現被它的外表給欺騙了。
但卻也為此深深愛上了它,是啊,這不就是我一直追求的嗎?無限的靈活性,可替換,越研究程式碼越發現處處都是精髓。
但在Laravel
中也不可避免的基礎MVC
模式,上述問題仍然存在。
初期使用
一直以為我都遵循一個核心:以倉庫層為處理資料基礎,為Serivce
和Controller
等提供資料供給,倉庫需要的原始資料則通過Model
中獲取。這樣可以完全分離Model
和Controller
的依賴。
最開始在Laravel
中使用是通過定義大量的RepositoryInterface
來注入,bind
,實現具體的Repository
工作類。
這是理想的使用方法可替換性很強。
遇到的問題
- 實際開發過程中
Repository
基本不會被替換,無數的Interface
帶來的規範,也帶來了開發的麻煩。 - 在使用
Repository
模式中我們不斷的注入Model
,每個方法都需要直接Model
來進行一次次的查詢資料集,卻失去了在外層鏈式呼叫的便捷性(這其實並不合理,但存在即有原由)。
中間的折中
後來索性在開發中我們去掉了Interface
的約束,直接作用功能類來注入使用,此時簡潔性和便捷性大大的提高,如果非要替換仍然bind
可以解決問題。這樣的開始一直持續很長時間。但是像連結呼叫仍然沒有解決,為些我們開發出了新的倉庫包。https://github.com/crcms/repository
再次輪迴
開始玩微服務,開始分離程式碼,當然就離不開RPC
,十分慶幸我們使用了Repository
模式,通過開啟對應的Rpc Repository
,我們可以很快進行本地Repository
切換,以Interface
來約束。
便捷的Repository包
基礎示例
class TestRepository extends AbstractRepository
{
/**
* @var array
*/
protected $guard = [
'id', 'title','other'
];
/**
* @return TestModel
*/
public function newModel(): TestModel
{
return app(TestModel::class);
}
/**
* @param int $perPage
* @return LengthAwarePaginator
*/
public function paginate(AbstractMagic $magic = null, int $perPage = 15): LengthAwarePaginator
{
$query = $this->where('built_in', 1);
if ($magic) {
$query->magic($magic);
}
return $query->orderBy($this->getModel()->getKeyName(), 'desc')->paginate($perPage);
}
/**
* @param int $name
* @param int $title
*/
public function updateName(string $name, string $title)
{
$this->getModel()->where('name', $name)->update(['title' => $title]);
}
}
超好用的Magic方法
在多條件搜尋中,肯定會存在大量的判斷,優雅度太低,如:
if($request->input('username')) {
$query->where('username',$username)
}
if($request->input('email')) {
$query->where('email',$email)
}
.......
但通過QueryMagic
方法我們可以輕鬆優雅解決這些問題,示例:
建立Magic
類
use CrCms\Repository\AbstractMagic;
use CrCms\Repository\Contracts\QueryRelate;
class TestMagic extends AbstractMagic
{
/**
* @param QueryRelate $queryRelate
* @param int $id
* @return QueryRelate
*/
protected function byName(QueryRelate $queryRelate, string $name)
{
return $queryRelate->where('name', $name);
}
/**
* @param QueryRelate $queryRelate
* @param string $title
* @return QueryRelate
*/
protected function byTitle(QueryRelate $queryRelate, string $title)
{
return $queryRelate->where('title', 'like', "%{$title}%");
}
/**
* @param QueryRelate $queryRelate
* @param int $id
* @return QueryRelate
*/
protected function byId(QueryRelate $queryRelate, int $id)
{
return $queryRelate->where('id', $id);
}
}
使用Magic
(這裡只是簡單示例):
public function paginate(array $condition, int $perPage = 15): LengthAwarePaginator
{
return $query->magic(new TestMagic($condition))->orderBy($this->getModel()->getKeyName(), 'desc')->paginate($perPage);
}
更多
開發此包的原因是在這之前我並示找到我想要的(適合我的)兼具Model
的靈活性以及資料倉儲的分離模式,所以為此開發了這個倉庫包。目前此包已經使用在好幾個專案中目前執行良好。
後面還打算相容TP
以及Yii
等使用率高的框架,暫時只支援Laravel
更多詳情,請移步github:https://github.com/crcms/repository
最後
哈哈,請原諒我著急的文字描述,希望對需要的人以及面臨和我曾經一樣困惑的人有所幫助。
原文出處:crcms-blog