Symfony2 DQL如何连接OneToMany关系中的最后一行

Symfony2 DQL如何连接OneToMany关系中的最后一行,symfony,doctrine,dql,Symfony,Doctrine,Dql,我有两个实体通过一对一的关系联系在一起: <?php namespace CRMBundle\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * User * * @ORM\Table() * @ORM\Entity(reposi

我有两个实体通过一对一的关系联系在一起:

<?php

namespace CRMBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * User
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="CRMBundle\Entity\ContactRepository")
 */
class User
{

/*...*/

    /**
     * @ORM\OneToMany(targetEntity="CRMBundle\Entity\Message", mappedBy="user", cascade={"persist"})
     * @ORM\OrderBy({"datetime" = "DESC"})
     */
    protected $messages;

/*...*/

}

我想你要找的是^^

您必须使用子查询动态选择一个用户消息的最新日期时间值,并加入具有此值的消息

为此,必须定义(子)查询,选择message.datetime的最大值:

$qb2= $this->createQueryBuilder('ms')
        ->select('MAX(ms.datetime) maxDate')
        ->where('ms.user = u')
        ;
然后在join子句中使用它,整个函数都在UserRepository中:

$qb = $this->createQueryBuilder('u');
$qb ->leftJoin('u.messages', 'm', 'WITH', $qb->expr()->eq( 'm.datetime', '('.$qb2->getDQL().')' ))
    ->addSelect('m');
然后,您的用户(每个用户)将拥有一个消息集合,其中包含一条消息(如果用户没有消息,则为null),您将通过以下方式获得该消息:

$user->getMessages()->first();
但是如果您使用Symfony的延迟加载功能,正如您已经在user.messages属性上定义了orderby注释一样,则调用

$user->getMessages()->first()
应将最新消息返回给您(但也将以静默方式加载所有其他消息)。 要避免此无提示的第二个DB查询,您可以将其直接加入请求用户的查询:

$qb = $this->createQueryBuilder('u');
$qb ->leftJoin('u.messages', 'm')
    ->addSelect('m');

“最后一条消息”是如何定义的?任何时间属性?按最高id(假设您使用序列整数作为主键)?我们无法根据您的问题进行回答。由于邮件是按升序日期时间排序的,因此我希望获得每个用户的最新邮件,然后请与我们共享您的邮件实体定义,至少是邮件的创建日期时间被持久化的属性我编辑了我的第一封邮件,以便您可以选择最大值(日期时间)在一个查询中按用户分组,并将其用作另一个选择中的子选择:选择用户,消息leftjoin message where message.id in(子选择)
$qb = $this->createQueryBuilder('u');
$qb ->leftJoin('u.messages', 'm')
    ->addSelect('m');