让我们打破你的好处之一清单按一个:
- 可测性(仓库可以被注入控制器)
这是真实的。后来在你的问题中,你说你可以轻松地将一个模型注入到控制器中,所以有什么意义?关键在于,如果使用接口来定义存储库方法,则可以在生产代码中使用具体存储库来实际查询雄辩模型,同时使用实现相同接口进行测试的“伪”存储库。我经常这样做,我的“假”实现只是使用一个Collection来保存我正在测试的模型。这样,您的测试运行得更快,您不必担心控制器测试中的迁移。它还使您不必在单元测试中与数据库进行交互。我并不是说它对数据库进行测试本质上是不好的,但是你应该在可能的情况下避免它。使用存储库可帮助您加速测试,而不需要需要与数据库进行交互。通过在您的控制器中键入存储库接口,您可以传入一个假实现进行测试,并将服务提供程序中的实际实现绑定到您的生产代码。
- 抽象(复杂口才查询可以被重构到存储库功能)
这是取决于你。 Laravel中存储库模式的问题在于,无论您尝试多么努力,模型都与数据库绑定。没有办法绕过它。您扩展应用程序并重新使用存储库的机会接近于零,因此这不一定是坏事。无论如何,业务逻辑不应该在您的模型或存储库中,所以应用程序的核心(如果设计正确)仍然会从框架中抽象出来。在真实的存储库模式中,您的查询是在存储库中定义的。但是由于Laravel的模型与数据库紧密耦合,放置这个逻辑的位置并不重要。事实上,Laravel具有一些很好的雄辩功能,可能会使这种逻辑在您的模型中变得更直观。在Laravel中,存储库的真正亮点就是我在第一点提出的,能够在测试中从数据库中进行一些抽象。
- 解耦(使我更换持久层)
这是存储库模式的主点和正是使得点#1可能。当然,传递Eloquent模型意味着无论模型在哪里,数据库也是如此。这只是你必须与Active Record共存的事情。
扩大对@ Lloope的回答,另一个好处是已经在一个地方定义了复杂的查询(无论是你的模型或仓库),以避免这样的代码在你的代码库乱丢:
$professor->getStudents()->orderBy('name')->get();
,而使用这样的事情:
$students = $usersRepository->getStudentsForProfessor($professor, 'name', 'ASC');
与写作各地您的应用程序雄辩查询的问题是,随着需求的变化,你必须更新这些查询在您的应用程序中的任这可能只是在您的控制器中,或在您的应用程序的几十个不同部分。一个存储库上的方法(或者甚至只是你的Eloquent模型)更容易维护。这意味着您的其他物体不需要担心getStudentsForProfessor
的功能或功能。他们只知道它会为给定的教授返回一批学生。存储库可以帮助您在一个地方组织查询逻辑。一旦你定义了这个界面,或者合同,你的其他对象可以依靠它来完成它所说的事情。随着查询需求的变化,您可以在一个地方更新实施,而不是在您的应用中全部更新。合同仍然是一样的。这比在任何地方编写雄辩的查询都有更大的灵活性。
如果您使用Eloquent,我建议您将所有数据相关逻辑放入模型中。如果你这样做,你仍然遵循存储库模式,并使用存储库包有太多的缺点,并没有给你任何真正重要的优势。如果您使用的是查询生成器或原始SQL查询,请使用存储库包。 –
Repository模式将帮助您将ORM作为一个整体进行替换,并使用其他一些OM,如Doctrine。如果您通过注入雄辩模型类来创建存储库,将来可以用一些其他ORM替换雄辩的ORM。但是,如果你只是想把雄辩分解成一个额外的抽象,那么它就毫无价值,而只是一种抽象。 – webDev