【问题标题】:Laravel - Using the Repository PatternLaravel - 使用存储库模式
【发布时间】:2014-03-15 09:11:37
【问题描述】:

我正在尝试学习存储库模式,但似乎对如何在急切加载关系并将数据库逻辑排除在我的控制器之外时如何使用此存储库模式感到有些困惑。

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

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 类中实现 with 方法,这将无法工作...

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 );
}

或者,我应该在我的类别存储库中实现 with 方法吗?

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

最后,我对Repository Pattern的用法的理解正确吗?

【问题讨论】:

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

标签: php service dependency-injection laravel repository-pattern


【解决方案1】:

您想多了,存储库只是您的controllermodel 之间的链接/桥梁,因此控制器直接使用repository 类而不是model,并且在该存储库中您可以使用声明您的方法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....我有一点问题。假设我通过控制器构造函数通过$this-&gt;model = somemodel() 分配模型实例。如果我使用存储库模式,我将创建接口、模型和服务提供者来注入。我可以轻松更改界面。 但是我也可以只更改构造函数中的模型(如上所述)并使用它....使用接口的实际好处是什么? (如果太宽泛,我会写一个问题,希望你能回答):)
  • 我想你错过了这个问题......或者我真的想多了。我知道如何从我的存储库中获取all。我已经在我的例子中做到了这一点。我想知道的是在使用接口时如何使用IOC到eager load。在您的回答中,它如何让我有能力做到这一点...$categories = $this-&gt;cat-&gt;with('products')-&gt;get(); 因为withCategoryInterface 中不存在我应该也实现它吗?还是应该创建一个同时使用两者的glue 存储库?
  • @itachi - 提出一个新问题,我会为你解答。
  • @Gravy,你不能在你的存储库中使用with,因为它没有被声明,但你可以使用Cat::with('products')-&gt;get()从你的存储库中使用它,并将它放在另一个方法中,即getCatWithProducts()。检查更新的答案。
【解决方案2】:

有一种非常简单的方法可以做到这一点,并且在此链接中对其进行了深入探讨

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);
}

在缺少某些功能时强制调用模型

【讨论】:

  • 感谢您的回答。在此站点中,我们非常感谢引用其来源的答案。但是单独的链接可能会在以后被破坏,所以您能否在内容中添加至少一些元素。
猜你喜欢
  • 2014-03-05
  • 2014-09-19
  • 2015-01-22
  • 2016-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-24
相关资源
最近更新 更多