场景:一个用户有多篇文章,查出多个用户,以及他们在某段时间内的文章。
用Laravel实现大概这样:
$users = User::with([
'posts' => function ($q) use ($month, $nextMonth) {
return $q->whereBetween('created_at', [$month, $nextMonth]); // 只eager load部分posts
}
])->whereIn('id', $userIDs)->get();
现在我用Doctrine是这样做的:
// $this是个EntityRepository
$users = $this->findAll(); // 查了全部用户,所用Post也查了全部
// 查询出相关的posts
$dql = "select r from Post r where r.createdAt> :month and r.createdAt < :next_month";
$query = $this->_em->createQuery($dql);
$query->setParameter(':month', $month)->setParameter(':next_month', $nextMonth);
$posts = $query->execute();
// 组装
foreach ($users as $user) {
$user->posts = new \Doctrine\Common\Collections\ArrayCollection();
foreach ($posts as $r) {
if ($r->user && $r->user->id == $user->id) {
$user->posts->add($r);
}
}
}
但是entity manager在persist的时候会重新加载全部records,所以在只有查询、没有保存的时候才能这样用。
在Doctrine中有更好的实现方法吗?或者有插件实现类似的功能?
两种解决方案:
CQRS,建独立的ReadModel
调整模型,增多一个月份关联