我只想弄清楚是否要使用存储库模式。 我能找到的三个好处是:
<button (click)="set value here"></button>
然而,除了第3点,我并没有真正清楚地看到它。
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)
因此,假设我并不关心与Eloquent的关系,我真的没有看到使用存储库的重点。我感谢任何改变主意的论据。
答案 0 :(得分:0)
从我的观点和经验来看,您可以使用Eloquent作为您的存储库层。
对于第2点,您可以创建范围方法,以便能够与普通的Eloquent查询一起使用
--full-index
我在过去几个月里对Laravel的存储库层有不同的经验:
bundle
,$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);
});
}
...... 如果您决定不创建如此多的特定方法,最终会得到一堆包含大量参数的方法
getUsersWithYellowCars()
有时您需要将模型传递到存储库以与它们进行交互,而不是直接与它进行交互
getUsersWithYellowCarsOrderedByName()
而不是
public function getUsersWithCars($color, $orderBy, $orderDescOrAsc, $paginate...)
一段时间后,代码看起来并不像预期的那样干净(请查看3中的示例。)
另外,想要说Eloquent已经是ORM,如果您决定从MySQL更改为SQLite,则无需更改代码中的任何内容。
答案 1 :(得分:0)
让我们逐一细分您的福利清单:
- 可测试性(可以将存储库注入控制器)
醇>
这是事实。在您的问题的后面,您说您可以轻松地将模型注入您的控制器,那么重点是什么?关键是如果使用接口来定义存储库方法,则可以使用生产代码中使用的具体存储库来实际查询雄辩模型,同时使用实现相同接口进行测试的“Fake”存储库。我经常这样做,我的“假”实现只使用一个集合来保存我正在测试的模型。这样,您的测试运行得更快,您不必担心控制器测试中的迁移。它还使您不必在单元测试中与数据库进行交互。 我并不是说测试数据库本身就不好,但你应该尽可能避免使用。使用存储库可以帮助您在不需要与数据库交互的情况下加速测试。通过在控制器中对存储库接口进行类型提示,您可以传入虚假实现进行测试,并在服务提供程序中为生产代码绑定实际实现。
- 抽象(复杂的雄辩查询可以重构为存储库函数)
醇>
这取决于你。 Laravel中存储库模式的问题在于,无论您如何努力,您的模型都与数据库绑定在一起。没有办法绕过它。您扩展应用程序并重新使用存储库的可能性几乎为零,因此这不一定是件坏事。无论如何,业务逻辑不应该在您的模型或存储库中,因此您的应用程序的核心(如果设计正确)仍将从框架中抽象出来。在真正的存储库模式中,您的查询在存储库中定义。但是由于Laravel的模型与数据库紧密耦合,因此将逻辑放在何处并不重要。事实上,Laravel有一些很好的Eloquent功能,可能会让这个逻辑在你的模型中更直接。存储库在Laravel中真正发挥作用的地方就是我在第一点上提到的,能够在测试中从数据库中抽象出来。
- 去耦(使我能够替换持久层)
醇>
这是存储库模式的要点,正是使得#1成为可能的原因。当然,传递Eloquent模型意味着无论模型在哪里,数据库也是如此。这只是你必须与Active Record一起生活的东西。
扩展@Lloope的答案,另一个好处是在一个位置(模型或存储库)中定义复杂查询,以避免在整个代码库中散布这样的代码:
$professor->getStudents()->orderBy('name')->get();
而是使用这样的东西:
$students = $usersRepository->getStudentsForProfessor($professor, 'name', 'ASC');
在您的应用中编写Eloquent查询的问题是,随着需求的变化,您必须在应用中的所有位置更新这些查询。这可能只在您的控制器中,或在您的应用程序的几十个不同部分。存储库(或者甚至只是您的Eloquent模型)上的getStudentsForProfessor
方法更容易维护。这意味着您的其他对象不需要担心getStudentsForProfessor
做什么或如何运作。他们只知道它会为给定的教授返回一批学生。存储库可帮助您在一个位置组织查询逻辑。定义此界面或合同后,您的其他对象可以依赖它来执行它所说的内容。随着查询要求的变化,您可以在一个位置更新实施,而不是在整个应用中更新。合同仍然是一样的。这比在任何地方编写Eloquent查询更具灵活性。