Laravel 存储库模式和多对多关系
Laravel Repository pattern and many to many relation
在我们的新项目中,我们决定使用六边形架构。我们决定使用存储库模式来获得更多的数据访问抽象。我们使用命令总线模式作为服务层。
在我们的仪表板页面中,我们需要大量数据,因此我们应该使用 3 级多对多关系(用户 -> 项目 -> 技能 -> 评论)并且技能应该是 active(status=1).
问题来了,这个应该放在哪里?
- $userRepository->getDashboardData($userId).
2.$userRepository->getUser($userId)->withProjects()->withActiveSkills()->withReviews();
3.$user = $userRepository->getById();
$projects = $projectRepository->getByUserId($user->id);
$skills = $skillRepository->getActiveSkillsByProjectsIds($projectIds);
在这种情况下,除了可以通过模型接口实现的接口编码外,我找不到存储库模式的好处。
我认为解决方案 3 是完美的,但它增加了很多工作。
您必须(例如)从面向对象的角度来决定返回的 "User" 是否包含一系列技能。如果是这样,您返回的用户将已经拥有这些对象。
在使用常规对象的情况下,尽量避免子实体,除非它很有意义。就像,例如.. 'User' 实体负责确保子实体遵守业务规则。 更喜欢使用不同的存储库 select基于任何其他标准的其他类型的实体。
以这种方式谈论 "relationship" 让我觉得您正在使用 ActiveRecord,否则它们只是子对象。 "relationship" 存在于关系数据库中。如果您将数据库记录/对象与 AR 混合使用,它只会潜入您的对象中。
在使用 ActiveRecord 对象的情况下,您可能会考虑在存储库上使用特定方法来加载正确配置的成员对象。 $members->allIncludingSkills()
之类的。 这是因为当返回多个实体时,你必须解决N+1。然后,你需要对结果集使用eager-loading,你不想使用相同的eager为每个请求加载配置。因此,您需要一种方法来描述每个请求的配置。一种方法是针对不同的请求在存储库上调用不同的方法。
然而,对我来说..我不希望有一堆只有..无限延伸的对象..例如..你可以有一个$member->posts[0]->author->posts[0]->author->posts[0]->author->posts[0]
。
我希望尽可能保持 'flat'。
$member = $members->withId($id);
$posts = $posts->writtenBy($member->id);
或类似的东西。 (只是在我的头顶打字)。
没有人喜欢大量的嵌套数组,ActiveRecord 可以被滥用到其对象本质上是具有方法的数组和无限嵌套的潜力。因此,虽然它可以是一种处理数据的便捷方式。我会努力防止滥用关系作为概念,并使您的结构尽可能平坦。
不仅可以在没有 ORM 'relationship' 功能的情况下进行编码。通常更容易。您可以看出此功能增加了很多麻烦,因为 ORM 必须在为了减轻痛苦。
真的,这有什么意义呢?它只是让您不必使用特定会员的 ID 来进行查找?我猜也许循环处理大量不同的东西更容易?
如果您希望能够单独测试您的代码,那么存储库实际上只在 ActiveRecord 情况下特别有用。否则,您可以使用 Laravel 的内置功能创建范围和诸如此类的东西,以防止到处都需要冗余(并因此变得脆弱)的查询逻辑。
创建专门为 UI 存在的模型也是完全合理的。 您可以拥有多个使用同一数据库的 ActiveRecord 模型 table,例如,您仅将其用于特定的用户界面用例。例如仪表板。如果你有一个新的用例..你只需创建一个新模型。
这对我来说.. 是设计系统的核心。问问我们自己……好吧,当我们有一个新的用例时,我们必须做什么?如果答案是肯定的,我们的架构是这样的,我们只做这个做这个,我们真的不必和其他人混在一起……那就太好了!否则,答案可能更像是..我不知道..我想修改所有内容并希望它有效。
有很多方法可以解决这个问题。但是,我建议避免使用大量复杂的工具来换取更简单的方法/解决方案。存储库是抽象数据持久性以允许进行隔离测试的好方法。如果要单独测试,请使用它。但是,我不确定我对 ORM 关系如何与对象模型一起工作有多少了解。
例如,我们是否有一些包含以下内容的大型 Member 对象?
- 该成员曾经留下的所有评论
- 成员拥有的所有技能
- 会员提出的所有推荐
- 会员已发送所有好友邀请
- 该会员建立的所有好友
我不喜欢这些巨大的物体被设计成只是容纳所有东西的容器的想法。我更喜欢将对象分解为专门为用例设计的位。
但是,我在胡说八道。简而言之..
- 不要滥用 ORM 关系功能。
- 最好有多个专门为用例设计的小对象,而不是几个什么都做的大对象。
只是我的 2 美分。
在我们的新项目中,我们决定使用六边形架构。我们决定使用存储库模式来获得更多的数据访问抽象。我们使用命令总线模式作为服务层。 在我们的仪表板页面中,我们需要大量数据,因此我们应该使用 3 级多对多关系(用户 -> 项目 -> 技能 -> 评论)并且技能应该是 active(status=1).
问题来了,这个应该放在哪里?
- $userRepository->getDashboardData($userId).
2.$userRepository->getUser($userId)->withProjects()->withActiveSkills()->withReviews();
3.$user = $userRepository->getById(); $projects = $projectRepository->getByUserId($user->id); $skills = $skillRepository->getActiveSkillsByProjectsIds($projectIds);
在这种情况下,除了可以通过模型接口实现的接口编码外,我找不到存储库模式的好处。 我认为解决方案 3 是完美的,但它增加了很多工作。
您必须(例如)从面向对象的角度来决定返回的 "User" 是否包含一系列技能。如果是这样,您返回的用户将已经拥有这些对象。
在使用常规对象的情况下,尽量避免子实体,除非它很有意义。就像,例如.. 'User' 实体负责确保子实体遵守业务规则。 更喜欢使用不同的存储库 select基于任何其他标准的其他类型的实体。
以这种方式谈论 "relationship" 让我觉得您正在使用 ActiveRecord,否则它们只是子对象。 "relationship" 存在于关系数据库中。如果您将数据库记录/对象与 AR 混合使用,它只会潜入您的对象中。
在使用 ActiveRecord 对象的情况下,您可能会考虑在存储库上使用特定方法来加载正确配置的成员对象。 $members->allIncludingSkills()
之类的。 这是因为当返回多个实体时,你必须解决N+1。然后,你需要对结果集使用eager-loading,你不想使用相同的eager为每个请求加载配置。因此,您需要一种方法来描述每个请求的配置。一种方法是针对不同的请求在存储库上调用不同的方法。
然而,对我来说..我不希望有一堆只有..无限延伸的对象..例如..你可以有一个$member->posts[0]->author->posts[0]->author->posts[0]->author->posts[0]
。
我希望尽可能保持 'flat'。
$member = $members->withId($id);
$posts = $posts->writtenBy($member->id);
或类似的东西。 (只是在我的头顶打字)。
没有人喜欢大量的嵌套数组,ActiveRecord 可以被滥用到其对象本质上是具有方法的数组和无限嵌套的潜力。因此,虽然它可以是一种处理数据的便捷方式。我会努力防止滥用关系作为概念,并使您的结构尽可能平坦。
不仅可以在没有 ORM 'relationship' 功能的情况下进行编码。通常更容易。您可以看出此功能增加了很多麻烦,因为 ORM 必须在为了减轻痛苦。
真的,这有什么意义呢?它只是让您不必使用特定会员的 ID 来进行查找?我猜也许循环处理大量不同的东西更容易?
如果您希望能够单独测试您的代码,那么存储库实际上只在 ActiveRecord 情况下特别有用。否则,您可以使用 Laravel 的内置功能创建范围和诸如此类的东西,以防止到处都需要冗余(并因此变得脆弱)的查询逻辑。
创建专门为 UI 存在的模型也是完全合理的。 您可以拥有多个使用同一数据库的 ActiveRecord 模型 table,例如,您仅将其用于特定的用户界面用例。例如仪表板。如果你有一个新的用例..你只需创建一个新模型。
这对我来说.. 是设计系统的核心。问问我们自己……好吧,当我们有一个新的用例时,我们必须做什么?如果答案是肯定的,我们的架构是这样的,我们只做这个做这个,我们真的不必和其他人混在一起……那就太好了!否则,答案可能更像是..我不知道..我想修改所有内容并希望它有效。
有很多方法可以解决这个问题。但是,我建议避免使用大量复杂的工具来换取更简单的方法/解决方案。存储库是抽象数据持久性以允许进行隔离测试的好方法。如果要单独测试,请使用它。但是,我不确定我对 ORM 关系如何与对象模型一起工作有多少了解。
例如,我们是否有一些包含以下内容的大型 Member 对象?
- 该成员曾经留下的所有评论
- 成员拥有的所有技能
- 会员提出的所有推荐
- 会员已发送所有好友邀请
- 该会员建立的所有好友
我不喜欢这些巨大的物体被设计成只是容纳所有东西的容器的想法。我更喜欢将对象分解为专门为用例设计的位。
但是,我在胡说八道。简而言之..
- 不要滥用 ORM 关系功能。
- 最好有多个专门为用例设计的小对象,而不是几个什么都做的大对象。
只是我的 2 美分。