为了举例:
我有以下架构:
users(id, name)
groups(id,name)
user_groups(user_id, group_id)
我想获取属于某个群组的用户。问题是,我知道组ID,所以我不想加入组表 - user_groups就足够了。
结果应该是
SELECT * FROM `users` AS u
LEFT JOIN `user_groups` AS ug ON (ug.`user_id` = u.`id)
WHERE ug.`group_id` = X
// i know the value of X
我在doctrine2中的尝试导致另一个groups
表的连接。
我最接近的是:
SELECT u FROM models\User u WHERE ?1 MEMBER OF u.groups
但它也将LEFT JOIN加入“WHERE EXISTS(...)”
可以在没有本机查询的情况下完成(使用DQL /查询构建器)吗?
答案 0 :(得分:3)
ORM优于ActiveRecord模式的一个优点是,您不需要为连接表创建新实体。
因此,当您使用Doctrine时,user_groups
表将在两侧进行映射。
这意味着您无法直接访问user_groups表。除非你使用本机sql,我强烈反对。
因此,解决您的情况的最佳方法是在群组回购中使用findOneBy($group_id)
并从中获取用户。这是理论上正确的实现方式。
- 编辑 - 您的评论:
是的,我同意从纯db POV中提高效率。但如果没有本机查询,你将无法做到这一点,因为DQL,查询构建器以及与doctrine相关的所有内容都使用Entities来执行操作,并且由于您在设计中使用ORM,因此您将没有实体用于Join表。
否则,唯一的方法是将地图从a many to many relation from user to groups using join table
更改为a one-to-many from users to user_groups and a many-to-one from user_groups to groups
。这样,您将拥有user_groups
的实体。
然后您可以直接使用该实体来获取用户。
即使它是一个黑客,它不是技术上和从理论上讲,这样使用是正确的。除非连接表当然还有其他责任。
答案 1 :(得分:0)
以下是您在DQL中的查询:
$query = $em->createQuery('SELECT u.id, u.name FROM Path\To\Users u LEFT JOIN u.groups g WHERE g.id = :group');
$query->setParameter('group', $group);
$users = $query->getResult();
我也倾向于在连接表方面考虑这样的查询,但是当你根据关联和实体包含的对象集合来思考时,Doctrine似乎更有意义。