我有一个可以有很多朋友的用户。意味着这种关系是自我引用的。 我现在需要根据他们的性别统计我的朋友朋友。到目前为止,我想出了以下解决方案。
我的用户实体:
<?php
namespace Acme\UserBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="Acme\UserBundle\Entity\Repository\UserRepository")
* @ORM\Table(name="users")
*/
class User extends BaseUser
{
/**
* @ORM\ManyToMany(targetEntity="Acme\UserBundle\Entity\User", inversedBy="friendsOf")
* @ORM\JoinTable(name="map_user_friend",
* joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="friend_id", referencedColumnName="id")}
* )
*/
protected $friends;
/**
* @ORM\ManyToMany(targetEntity="Acme\UserBundle\Entity\User", mappedBy="friends")
*/
private $friendsOf;
/**
* @ORM\Column(type="string", length=1, nullable=true)
*/
protected $gender;
// other fields ...
}
我的UserRepository有以下方法:
public function getFriendsQuery(User $user)
{
return $this->getEntityManager()->createQueryBuilder()
->select('u as user, COUNT(DISTINCT mf.id) as male_friends, COUNT(DISTINCT ff.id) as female_friends')
->from('Oneup\UserBundle\Entity\User', 'u')
->leftJoin('u.friendsOf', 'f')
->leftJoin('u.friendsOf', 'mf', 'with', 'mf.gender = :gender')->setParameter('gender', 'm')
->leftJoin('u.friendsOf', 'ff', 'with', 'ff.gender = :gender')->setParameter('gender', 'w')
->where('f = :user')->setParameter('user', $user)
->groupBy('u.id')
;
}
在控制器中,我现在首先通过Doctrine\Common\Util\Debug::dump($qb->getQuery()->getSQL());
转储SQL,返回
SELECT u0_.username AS username0,
u0_.username_canonical AS username_canonical1,
-- ... --
u0_.gender AS gender19,
-- ... --
COUNT(DISTINCT u1_.id) AS sclr32,
COUNT(DISTINCT u2_.id) AS sclr33
FROM users u0_
LEFT JOIN map_user_friend m4_ ON u0_.id = m4_.friend_id
LEFT JOIN users u3_ ON u3_.id = m4_.user_id
LEFT JOIN map_user_friend m5_ ON u0_.id = m5_.friend_id
LEFT JOIN users u1_ ON u1_.id = m5_.user_id
AND (u1_.gender = ?)
LEFT JOIN map_user_friend m6_ ON u0_.id = m6_.friend_id
LEFT JOIN users u2_ ON u2_.id = m6_.user_id
AND (u2_.gender = ?)
WHERE u3_.id = ?
GROUP BY u0_.id
男性为m
,女性为f
,当前用户为21
。现在遵循奇怪的行为。 Doctrine\Common\Util\Debug::dump($qb->getQuery()->execute());
让我回复
array (size=2)
0 =>
array (size=3)
'user' => string 'Oneup\UserBundle\Entity\User' (length=28)
'male_friends' => string '2' (length=1)
'female_friends' => string '2' (length=1)
1 =>
array (size=3)
'user' => string 'Oneup\UserBundle\Entity\User' (length=28)
'male_friends' => string '0' (length=1)
'female_friends' => string '0' (length=1)
如果我在mysql中直接执行查询,我会得到另一个计数:
+--------------+-----------------+-----------------+
| username0 | sclr32 (male) | sclr33 (female) |
+--------------+-----------------+-----------------+
| foobar12 | 1 | 2 |
+--------------+-----------------+-----------------+
| foobar2 | 2 | 0 |
+--------------+-----------------+-----------------+
这是正确的。这是一个学说错误,还是我只是做错了?
答案 0 :(得分:0)
要回答我自己的问题,错误在于存储库
中的参数 ->leftJoin('u.friendsOf', 'mf', 'with', 'mf.gender = :gender')->setParameter('gender', 'm')
->leftJoin('u.friendsOf', 'ff', 'with', 'ff.gender = :gender')->setParameter('gender', 'w')
错了。 doctrine获取两个条目的第二个值。
->leftJoin('u.friendsOf', 'mf', 'with', 'mf.gender = :male')->setParameter('male', 'm')
->leftJoin('u.friendsOf', 'ff', 'with', 'ff.gender = :female')->setParameter('female', 'w')