首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >laravel将抽象置于模型中而不是存储库中。

laravel将抽象置于模型中而不是存储库中。
EN

Stack Overflow用户
提问于 2017-10-20 21:10:31
回答 2查看 1.1K关注 0票数 1

我只是想弄清楚我是否想使用存储库模式。我能找到的三个优点是:

代码语言:javascript
复制
1. Testability (repositories can be injected into the controller)
2. Abstraction (complex eloquent queries can be refactored into repository functions)
3. Decoupling (enables me to replace the persistence layer)

然而,除了第3点,我并没有清楚地看到这一点。

代码语言:javascript
复制
1. I can just as well inject the model (or a mock for testing)
2. I can also abstract the queries into functions and place them into the model instead of a repository.

因此,假设我不关心与雄辩的关系,我不认为使用存储库有什么意义。我很感激任何能改变我主意的论点。

EN

回答 2

Stack Overflow用户

发布于 2017-10-20 23:48:54

从我的观点和经验来看,您可以使用雄辩作为存储库层。

对于第2点,您可以创建范围方法,以便能够与正常的雄辩查询一起使用。

代码语言:javascript
复制
$users = User::whereHasACarOfColor('yellow')->where('active, true)->get();
// ...
public function scopeWhereHasACarOfColor($query, $color) 
{
    return $this->whereHas(function ($cars) use ($color) {

        return $cars->where('color', $color);

    });
} 

在过去的几个月里,我对Laravel中的存储层有着不同的体验:

  1. 由于我想重用代码,所以我不得不创建许多类似的方法,getUsersWithYellowCars()getUsersWithYellowCarsOrderedByName().
  2. 如果您决定不创建这么多特定的方法,那么最终您将得到一堆具有很多参数的方法。 公共职能getUsersWithCars($color,$orderBy,$orderDescOrAsc,$paginate.)
  3. 有时,您需要将模型传递给存储库以与它们交互,而不是直接与其交互。 $usersRepository->getStudentsForProfessor($professor,‘$students’,'ASC'); 而不是 $professor->getStudents()->orderBy('name')->get();= $students
  4. 一段时间后,代码看起来不像预期的那么清晰(请参阅3中的示例)。

另外,想说雄辩已经是一个ORM,如果您决定从MySQL更改为SQLite,您就不必更改代码中的任何内容。

票数 0
EN

Stack Overflow用户

发布于 2017-10-20 23:58:42

让我们逐一列出你的利益清单:

  1. 可测试性(可以将存储库注入控制器)

这是真的。在后面的问题中,您说您可以很容易地将一个模型注入到控制器中,那么这有什么意义呢?关键是,如果您使用一个接口来定义存储库方法,那么您可以在生产代码中使用具体的存储库来实际查询雄辩的模型,同时使用实现相同接口进行测试的“假”存储库。我经常这样做,我的“假”实现只是使用一个集合来保存我正在测试的模型。这样,您的测试运行得更快,并且不必担心控制器测试中的迁移。它还使您不必与单元测试中的数据库进行交互。--我并不是说对数据库进行测试本质上是不好的,但是您应该尽可能避免使用。使用存储库可以帮助您在不需要与数据库交互的情况下加快测试速度。通过在控制器中输入Repository接口,您可以传递一个假的实现来测试,并在生产代码的Service中绑定一个真正的实现。

  1. 抽象(复杂的、雄辩的查询可以重构为存储库函数)

这取决于你。Laravel中存储库模式的问题是,无论您多么努力地尝试,您的模型都绑定到数据库中。没有办法可以绕过它。扩展应用程序和重用存储库的可能性几乎为零,因此这并不一定是坏事。无论如何,业务逻辑不应该出现在您的模型存储库中,因此您的应用程序的核心(如果设计得当)仍将从框架中抽象出来。在真正的存储库模式中,查询是在存储库中定义的。但是,由于Laravel的模型与数据库紧密耦合,所以您把这个逻辑放在哪里并不重要。事实上,Laravel有一些很好的口才特性,这可能会使您的模型中的逻辑变得更正确。在Laravel中,存储库是我在第一点中提到的,能够在测试中从数据库中抽象一些。

  1. 解耦(使我能够替换持久性层)

这是存储库模式的要点,也正是使第1点成为可能的原因。当然,传递雄辩的模型意味着无论模型在哪里,数据库也是如此。这只是你必须接受的活动记录。

扩展@Lloope的答案,另一个好处是将复杂的查询定义在一个位置(您的模型或存储库),以避免这样的代码散落在代码库中:

代码语言:javascript
复制
$professor->getStudents()->orderBy('name')->get();

取而代之的是这样的用法:

代码语言:javascript
复制
$students = $usersRepository->getStudentsForProfessor($professor, 'name', 'ASC');

在您的应用程序中编写出色的查询的问题是,随着需求的变化,您必须在应用程序中的任何地方更新这些查询。这可能只是在您的控制器一次,或在您的应用程序的几十个不同的部分。存储库上的getStudentsForProfessor方法(甚至仅仅是雄辩的模型)更易于维护。这意味着您的其他对象不需要担心getStudentsForProfessor做什么或者它是如何工作的。他们只是知道它将返回一组学生给给定的教授。存储库可以帮助您将查询逻辑组织在一个地方。一旦定义了这个接口或契约,其他对象就可以依赖它来执行它说的了。随着查询需求的变化,您可以在一个地方而不是在整个应用程序中更新实现。合同还是一样的。这比在任何地方编写有说服力的查询都灵活得多。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46857389

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档