Php 处理与数据映射器模式的关系

Php 处理与数据映射器模式的关系,php,design-patterns,orm,datamapper,Php,Design Patterns,Orm,Datamapper,我正在使用数据映射器模式,我想知道处理与该模式的关系的最佳方法是什么。我花了很多时间在Google和Stack overflow中搜索解决方案,我找到了一些,但我仍然对它们不太满意,特别是在一个我将尝试解释的特殊情况下 我正在使用PHP,因此我将使用PHP编写代码示例 假设我有一个表“team”(id,name)和一个表“player”(id,name,team_id)。这是一种1-N关系。 通过实现数据映射器模式,我们将拥有以下类:Team、TeamMapper、Player和PlayerMa

我正在使用数据映射器模式,我想知道处理与该模式的关系的最佳方法是什么。我花了很多时间在Google和Stack overflow中搜索解决方案,我找到了一些,但我仍然对它们不太满意,特别是在一个我将尝试解释的特殊情况下

我正在使用PHP,因此我将使用PHP编写代码示例

假设我有一个表“team”(id,name)和一个表“player”(id,name,team_id)。这是一种1-N关系。 通过实现数据映射器模式,我们将拥有以下类:Team、TeamMapper、Player和PlayerMapper

到目前为止,一切都很简单。如果我们想从一个团队中得到所有的球员呢

我找到的第一个解决方案是在Team类中创建一个方法getAllPlayer(),该方法将通过延迟加载和代理来处理该问题。然后,我们可以找回这样一支球队的球员:

$players = $team->getAllPlayers();
$playerMapper->findAll(array('team_id' => $teamIds));
我发现的第二个解决方案是直接使用PlayerMapper并将团队ID作为参数传递。比如:

$playerMapper->findAll(array('team_id' => $team->getId()));
但是现在,让我们假设我想显示一个包含所有团队的HTML表,以及一个包含每个团队所有成员的列“Players”。如果我们使用我描述的第一个解决方案,我们必须执行一个SQL查询来获取团队列表,每个团队执行一个查询来获取球员,这意味着N+1个SQL查询,其中N是团队数量

如果我们使用我描述的第二个解决方案,我们可以首先检索所有团队ID,将它们放入一个数组中,然后将其传递给玩家映射器的findAll方法,类似这样:

$players = $team->getAllPlayers();
$playerMapper->findAll(array('team_id' => $teamIds));
在这种情况下,我们只需要运行2个查询。好多了。但是我仍然对这个解决方案不太满意,因为模型中没有描述关系,开发人员必须了解它们

所以我的问题是:有没有其他的数据映射器模式的替代方案?在我给出的例子中,是否有一种好的方法可以在2个查询中选择所有队员的所有团队,并在模型中描述关系


提前谢谢你

如果您查看Martin Fowler描述数据映射器工作原理的文本,您会发现您可以使用一个查询来获取所需的所有数据,然后将这些数据传递给每个映射器,从而使映射器只挑选出所需的数据

对于您来说,这将是一个从一个团队连接到另一个玩家的查询,返回一个结果集,其中包含每个唯一玩家的重复团队数据

然后,您必须只在数据更改时创建新对象,以满足映射代码中的重复

我做过类似的事情,等价的是团队映射器迭代结果集,对于每个唯一的团队,将结果集传递给玩家映射器,以便它可以创建一个玩家,然后将玩家添加到团队集合中


虽然这会起作用,但这种方法在下游还有一些问题…

我有一个可能的解决方案,我已经在我的一个项目中成功地实现了。它不是那么复杂,在上面描述的示例中只使用2个查询

解决方案是添加另一层负责处理关系的代码

例如,我们可以将其放在服务类中(也可以用于其他内容,而不仅仅是处理关系)。 假设我们在Team和TeamMapper之上有一个类TeamService。TeamService将有一个方法getTeamsWithRelationships(),该方法将返回一个团队对象数组。getTeamsWithRelationships()将使用TeamMapper获取团队列表。然后,使用PlayerMapper,它将只在一个查询中获取这些团队的球员列表,并使用Team类中的setPlayers()方法将球员设置为各个团队


此解决方案非常简单,易于实现,并且适用于所有类型的数据库关系。我想有些人可能会反对它。如果是的话,我想知道问题是什么?

你指的是哪本马丁·福勒的书?我找到的唯一一个是那一个,我看不出你说的是什么。无论如何,这种方法不能说服我。这意味着您必须执行一个查询,返回包含大量重复数据的NxM行(N为团队数量,M为玩家数量)。它还意味着通过团队映射器映射球员,这听起来不太好。正如你所说的,我确信这种方法在下游会有问题……它在PoEAA的书中。该网站仅提供概述。您的查询不返回NxM行,只返回M行。它确实带回了很多数据,但这就是重点。在一次往返中尽可能多地抓取。此外,您的团队映射器不映射玩家,它要求玩家映射器为其映射玩家。是的,对不起,M行。嗯,这是一个解决办法,但我仍然不完全相信。让我们看看我的问题是否会带来更多的答案。@Vincent:你还没有完全被说服,但不要说为什么-由于没有接受答案,这个评论对那些未来寻求帮助的人来说是没有用的。@DavidOsborne:下游还有什么问题?