Vin*_*ent 10 php orm design-patterns datamapper
我正在使用Data Mapper模式,我想知道处理与该模式的关系的最佳方法是什么.我花了很多时间在谷歌搜索解决方案和堆栈溢出,我发现了一些,但我仍然不是很满意他们,特别是在我将尝试解释的一个特殊情况.
我正在使用PHP,所以我将放在PHP中的代码示例.
假设我有一个表"团队"(id,name)和一个表"player"(id,name,team_id).这是一个1-N的关系.通过实现Data Mapper模式,我们将拥有以下类:Team,TeamMapper,Player和PlayerMapper.
到目前为止,一切都很简单.如果我们想要从团队中获得所有玩家怎么办?
我找到的第一个解决方案是在Team类中创建一个方法getAllPlayers(),它将使用延迟加载和代理来处理它.然后,我们可以检索这样一个团队的玩家:
$players = $team->getAllPlayers();
Run Code Online (Sandbox Code Playgroud)
我找到的第二个解决方案是直接使用PlayerMapper并将团队ID作为参数传递.就像是:
$playerMapper->findAll(array('team_id' => $team->getId()));
Run Code Online (Sandbox Code Playgroud)
但现在,让我们说我希望显示一个包含所有团队的HTML表格,以及每个团队所有玩家的"玩家"栏目.如果我们使用我描述的第一个解决方案,我们将不得不做一个SQL查询来获取团队列表和每个团队的一个查询来获取玩家,这意味着N + 1个SQL查询,其中N是团队数量.
如果我们使用我描述的第二个解决方案,我们可以先检索所有团队ID,将它们放在一个数组中,然后将其传递给播放器映射器的findAll方法,如下所示:
$playerMapper->findAll(array('team_id' => $teamIds));
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我们只需要运行2个查询.好多了.但我对这个解决方案仍然不满意,因为关系没有被描述到模型中,开发人员必须了解它们.
所以我的问题是:Data Mapper模式还有其他替代方案吗?通过我给出的示例,是否有一种很好的方法可以在2个查询中选择所有参与者的所有团队,并描述模型中的关系?
先感谢您!
如果您查看 Martin Fowler 描述 DataMapper 如何工作的文本,您会发现可以使用一个查询来获取所需的所有数据,然后将该数据传递给每个映射器,从而允许映射器仅挑选出数据它需要的。
对于您来说,这将是一个从团队连接到玩家的查询,返回一个结果集,其中包含每个唯一玩家的重复团队数据。
然后,您必须通过仅在数据更改时创建新对象来满足映射代码中的重复。
我做了类似的事情,其中等效的是团队映射器迭代结果集,并且对于每个唯一的团队将结果集传递给玩家映射器,以便它可以创建一个玩家,然后将玩家添加到团队的集合中。
虽然这可行,但这种方法在下游存在问题......