Laravel##laravel中使用Repository 讓
文章正文Repository 模式主要想法是建立在一個資料操作代理層上的,把controller裡的資料運算分離出來,這樣做的好處有以下幾點:
1 把資料處理邏輯分離讓程式碼更容易維護
2 資料處理邏輯和業務邏輯分離,可以將這兩個程式碼分別進行測試
3 減少程式碼重複
4 降低程式碼出錯的幾率
#5 讓controller程式碼的可讀性大大提高
如圖所示Repository的分層關係
然而,要獨立一個操作層出來,那就會增加大量程式碼,非常繁瑣。如果你是小項目,未必需要使用這個模式。但如果是4-5年以上的複雜大型項目,這種模式的好處就比較明顯了。
學習Repository Pattern的意義不只是為了使用它,更會讓你深入思考框架的分層思想,你開始不僅關注怎麼使用一個框架,還會想了解怎樣設計一個框架,也許會成為你往高階段編程的入口。當你感悟到什麼是一種想法的時候。 。 。
public function index(){ $posts = Post::whereIn('category_id',[1,2]) ->where('is_draft',0) ->orderBy('created_at', 'desc') ->take(5) ->get(); return view('front.index',compact('posts'));}
以上是典型的Eloquent資料查詢程式碼,如果你程式設計經驗豐富,你會發現這種程式碼在控制器裡到處都是,而且有很多是重複的,可讀性很差;我們的目標是把它精簡:
仔細觀察
Post::whereIn('category_id',[1,2])->where('is_draft',0)->orderBy('created_at', 'desc')->take(5)->get();
其實它由3部分組成.
第一是
Post資料模型;第二個是
,資料操作條件;第三個是
資料取得的方法;我們知道,
裡面有個Query Scope
,可以用來把第二部分,也就是查詢條件精簡。所以,在使用了Query Scope
後,我們可以把精簡成:<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">Post::ofCategory([1,2])->isDraft()->orderBy('created_at', 'desc')->take(5)->get();</pre><div class="contentsignin">登入後複製</div></div>
咋一看上去,好像也沒怎麼精簡啊,但實際上你已經實現程式碼解耦和復用了,比如說
, 這個程式碼可以到處用,不用擔心耦合問題。 精簡程度和你的邏輯抽象程度有關,比如說你完全可以寫成:
Post::findPosts([1,2],0,'desc',5)->get();
在輕型專案中,強烈建議使用
Query Scope,這是一種良好的程式設計習慣。 在更複雜的專案中,
就不夠用了,因為它和資料模型還是一種強耦合,Repository Pattern
就是要把第一,第二,第三部分全部解耦;說到解耦,我們在
的文檔攻略中講過,第一神器就是PHP中的介面( Interface
)
下面來看範例
第一步建立資料夾
app Repositories Interfaces Implements
Interfaces裡面用來放接口,Implements用來放介面的實作;
第二步驟 建立一個介面
在上方的
Interfaces目錄新建一個檔案PostInterface.php
: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">namespace App\Repositories\Interfaces;Interface PostInterface{
public function findPosts(Array $cat_id,$is_draft,$order,$take) {
}}</pre><div class="contentsignin">登入後複製</div></div>
第三步驟 建立一個介面對應的實作
在上面的
Implements目錄新建一個檔案PostRepository.php
:<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">namespace App\Repositories\Implements;use Post;class PostRepository Implements PostInterface{
public function findPosts(Array $cat_id,$is_draft,$order,$take){
$query = Post::whereIn('category_id',$cat_id)
->where('is_draft',$is_draft)
->orderBy('created_at', $order)
->take($take)
->get();
return $query;
}}</pre><div class="contentsignin">登入後複製</div></div>
很明顯,倉庫指的就是一個倉庫介面的實作;這裡定義你的業務邏輯;
第四步 在ServiceProvider中綁定介面
開啟
app/Providers/AppServiceProvider, 在register()
加入程式碼:<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><?php namespace App\Providers;use Illuminate\Support\ServiceProvider;class AppServiceProvider extends ServiceProvider{
public function boot(){
}
public function register(){
$this->app->bind('App\Repositories\Interfaces\PostInterface', 'App\Repositories\Implements\PostRepository');
}}</pre><div class="contentsignin">登入後複製</div></div>
我們知道,ServiceProvider是Laravel IOC容器實作動態換介面實作的地方,所以我們在這裡綁定一下,這樣我們使用的時候,不直接使用介面實現,而是用ioc容器解析接口,它會幫你自動找到對應好的實作。這意味著,以後需要更換實現,可以在這裡更換;
第五步 使用倉庫
回到我們的controller裡來
use App\Repositories\Interfaces\PostInterface;class PostController extends BaseController{ public function __construct(PostInterface $post){ $this->postRepo = $post; } public function index(){ $this->postRepo->findPosts([1,2],0,'desc',5); }}
从上面的例子看,我们的业务逻辑变得非常精简,完全不用管查询;而且也现实了数据查询部分的解耦。
以上是在laravel使用Repository Pattern(倉庫模式)的詳細內容。更多資訊請關注PHP中文網其他相關文章!