我正在构建一个简单的消息传递系统。用户与ManyToMany关系中的MessageThreads相关。 MessageThreads可以有很多用户(例如,群聊或频道),也可以只有两个用户(例如,私人消息)。
class User extends BaseUser
{
/**
* HAS MANY: MessageThreads
* @ORM\ManyToMany(targetEntity="MessageThread", inversedBy="users", fetch="EXTRA_LAZY", cascade={"persist"})
* @ORM\JoinTable(
* name="user_message_thread",
* joinColumns={
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="mthread_id", referencedColumnName="id")
* }
* )
*/
private $messageThreads;
...
}
class MessageThread
{
/**
* HAS MANY: Users
* @ORM\ManyToMany(targetEntity="User", mappedBy="messageThreads", cascade={"persist"})
*/
private $users;
...
}
现在考虑到该用户具有与某些其他用户打开私人聊天的方法,我希望能够确定他们之间是否已经有一个MessageThread(仅限他们),还是应该创建一个新的
public function newPrivAction(Request $request, string $slug)
{
...
// try locating a thread with ONLY current and $friend user
if($thread = $em->getRepository('AppBundle:MessageThread')->findOnePrivFor($this->getUser(), $friend)) {
// ** dbg
print "Old priv found #" . $thread->getId();
die();
}
// or create a brand new thread
else {
$thread = new MessageThread();
$thread
->addUser($this->getUser())
->addUser($friend)
;
$em->persist($thread);
$em->flush();
// ** dbg
print "New priv created #" . $thread->getId();
die();
}
...
}
我的问题是我无法真正弄清楚如何构造findOnePrivFor(...)
存储库方法。理想情况下,我想要一个只能找到只有该用户的线程的方法,但是经过几个小时的搜索后,我放弃了。我的第二种方法(或更确切地说,解决方法)是找到属于给定线程的用户,并将用户数限制为2。这与我非常接近-除了计数部分似乎不起作用。
class MessageThreadRepository extends \Doctrine\ORM\EntityRepository
{
public function findOnePrivFor(User $user1, User $user2)
{
$qb = $this->createQueryBuilder('mt');
$qb
->where(':user1 MEMBER OF mt.users')
->andWhere(':user2 MEMBER OF mt.users')
//->andWhere('count(mt.users) = 2') // ** fails
//->andWhere($qb->expr()->eq($qb->expr()->count('mt.users'), 2)) // ** fails
->setMaxResults(1)
->setParameters([
'user1' => $user1,
'user2' => $user2
])
;
return $qb->getQuery()->getOneOrNullResult();
}
}
任何帮助将不胜感激。
答案 0 :(得分:-1)
在查询生成器中添加一个having子句:
$qb->join('mt.users', 'u')
->having('count(u.id) = 2'))