2014-02-16 64 views
11

我正在尝试学习存储库模式,似乎让我自己有点混淆,因为我急于加载关系时如何使用这个存储库模式,并将数据库逻辑保留在我的控制器之外。Laravel - 使用存储库模式

我的存储库/应用程序结构的快速概览。

app/ 
    Acme/ 
    Repositories/ 
     RepositoryServiceProvider.php 
     Product/ 
     EloquentProduct.php 
     ProductInterface.php 
     Category/ 
     EloquentCategory.php 
     CategoryInterface.php 

例ProductInterface.php

<?php namespace GD\Repositories\Product; 

interface ProductInterface 
{ 
    public function all(); 

    public function find($id); 

    public function findBySlug($slug); 
} 

例CategoryInterface.php

<?php namespace GD\Repositories\Category; 

interface CategoryInterface 
{ 
    public function all(); 

    public function find($id); 

    public function findBySlug($slug); 
} 

好了,所以比较容易的部分是利用DI喷射模型的依赖关系到控制器中。

列出所有类别相关产品更困难,因为我不再使用雄辩模型。我正在使用一个没有公开所有雄辩方法的界面。

这不会没有我实现我的EloquentCategory类中方法工作...

public function show($slug) 
{ 
    return Response::json($this->category->findBySlug($slug)->with('products'), 200); 
} 

我应该创建一个单独的服务类两个储存粘合在一起?例如允许以下内容

public function __construct(ShopService $shop) 
{ 
    $this->shop = $shop; 
} 

public function show($slug) 
{ 
    return Response::json($this->shop->getProductsInCategory($slug), 200); 
} 

或者,我是否应该在我的Category Repository中实现with方法?

public function with($relation) 
{ 
    return Category::with($relation); 
} 

最后,我是否理解了Repository Pattern的用法正确?

+5

app/Acme/etc ...有人来自laracasts:P –

回答

17

你是在思考,仓库只是之间的链接/桥梁您controllermodel,因此控制器直接在库中,您可以声明使用model从那里你的方法,例如使用repository类,而不是model

<?php namespace GD\Repositories\Category; 

interface CategoryInterFace{ 

    public function all(); 

    public function getCategoriesWith($with); 

    public function find($id); 
} 

现在实施库类接口:

<?php namespace GD\Repositories\Category; 

use \EloquentCategory as Cat; // the model 
class CategoryRepository implements CategoryInterFace { 
    public function all() 
    { 
     return Cat::all(); 
    } 

    public function getCategoriesWith($with) 
    { 
     return Cat::with($with)->get(); 
    } 

    public function find($id) 
    { 
     return Cat::find($id): 
    } 
} 

要在你的控制器使用方法:

<?php 

use GD\Repositories\Category\CategoryInterFace; 

class CategoryController extends BaseController { 

    public function __construct(CategoryInterFace $category) 
    { 
     $this->cat = $category; 
    } 

    public function getCatWith() 
    { 
     $catsProd = $this->cat->getCategoriesWith('products'); 
     return $catsProd; 
    } 

    // use any method from your category 
    public function getAll() 
    { 
     $categories = $this->cat->all(); 

     return View::make('category.index', compact('categories')); 
    } 

} 

注:仓库的省略IoC结合,因为这不是你的问题,你知道的。

更新:我在这里写了一篇文章:LARAVEL – USING REPOSITORY PATTERN

+1

+1 ....我有一个小问题。假设我通过控制器构造函数通过'$ this-> model = somemodel()'来分配一个模型实例。如果我使用存储库模式,我将创建接口,模型和服务提供者来注入。我可以轻松更改界面。 __but__我也可以在构造函数中更改模型(如上所述)并使用它....使用接口的实际好处是什么? (如果它太宽泛,我会写一个问题,并希望你会回答):) – itachi

+0

我想你已经错过了这个问题......或者我真的在想什么。我知道如何从我的存储库中获得'all'。我已经在我的例子中完成了。我想知道的是如何在使用接口时使用IOC来“加载”。在你的答案中,它是如何给我这样做的......'$ categories = $ this-> cat-> with('products') - > get();'因为'with'不存在于'CategoryInterface'我应该实现吗?或者我应该创建一个同时使用两者的'glue'仓库? – Gravy

+0

@itachi - 开始一个新的问题,我会为你回答。 – Gravy

1

有一个非常简单的方法来做到这一点,它是深入探讨在这个环节

http://heera.it/laravel-repository-pattern#.U6XhR1cn-f4

我一直在寻找确切的解决方案,它运作良好,到目前为止

所以您的想法将是在您的存储库代码中声明这个

public function __construct(\Category $category) 
{ 
    $this->category = $category; 
} 
public function getAllUsers() 
{ 
    return $this->category->all(); 
} 

public function __call($method, $args) 
{ 
    return call_user_func_array([$this->category, $method], $args); 
} 

强制模型被调用时,一些功能是失踪

+0

谢谢你的回答。在这个网站,我们很欣赏引用他们的来源的答案。但是链接本身可以在以后被破解,所以你可以在内容中添加至少一些元素。 –