Doctrine - OneToMany 关系,所有结果行都不会在对象中获取

Doctrine - OneToMany relation, all result row doesn't fetch in object

我尝试获取我的所有对象 DemandCab 及其子对象 (DecisionCab)。

我的 2 个实体

/**
 * DemandCab.
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="DemandCabRepository")
 */
class DemandCab
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
     private $id;

    /**
     * @var DecisionCab
     *
     * @ORM\OneToMany(targetEntity="\My\CabBundle\Entity\DecisionCab", mappedBy="demandCab")
     */
     private $decisionsCab;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="startDate", type="datetime")
     */
     private $startDate;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="endDate", type="datetime", nullable=true)
     */
     private $endDate;

    /**
     * @var int
     *
     * @ORM\Column(name="followup", type="integer", nullable=true)
     */
     private $followup;

    /**
     * @var InfoCab
     *
     * @ORM\ManyToOne(targetEntity="\My\CabBundle\Entity\InfoCab", inversedBy="demandsCab")
     */
     private $infoCab;

}

/**
 * DecisionCab.
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="DecisionCabRepository")
 */
 class DecisionCab
 {
     /**
      * @var int
      *
      * @ORM\Column(name="id", type="integer")
      * @ORM\Id
      * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

     /**
      * @var DemandCab
      *
      * @ORM\ManyToOne(targetEntity="\My\CabBundle\Entity\DemandCab", inversedBy="decisionsCab")
      */
     private $demandCab;

    /**
     * @var bool
     *
     * @ORM\Column(name="decision", type="boolean", nullable=true)
     */
     private $decision;

    /**
     * @var string
     *
     * @ORM\Column(name="motif", type="string", length=500, nullable=true)
     */
     private $motif;

    /**
     * @var string
     *
     * @ORM\Column(name="role", type="string", length=255)
     */
     private $role;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="date", type="datetime", nullable=true)
     */
     private $date;

    /**
     * @var DemandCab
     *
     * @ORM\ManyToOne(targetEntity="\My\CabBundle\Entity\DemandCab", inversedBy="decisionsCab")
     */
     private $demandCab;

    /**
     * @var User
     *
     * @ORM\ManyToOne(targetEntity="\My\CabBundle\Entity\User", inversedBy="decisionsCab")
     */
    private $user;
}

在我的 DemandCabRepository 中

public function findAllCompleted(){
    $qb = $this->createQueryBuilder("dem");
    $qb->select('dem, dec');
    $qb->leftJoin("dem.decisionsCab", "dec");
    $qb->andWhere("dem.completed = 1");
    $qb->orderBy("dem.startDate", "DESC");

    return $qb->getQuery()->getResult();
}

我的 DemandCab 数据

我的 DecisionCab 数据

当我转储结果时,只出现 2 个决定...

... 而当我使用 getArrayResult 时,我有 4 个决定...

查询很好,但我不明白为什么 hydration 会删除属性 decision 为 0 或 1 的 DecisionCab 对象(仅显示 null)。

我想了解为什么以及是否有解决方案来获取包含所有 DecisionCab 子对象的 DemandCab 对象。

谢谢

首先,您已使用带有 ArrayCollection 的 ManyToOne 关系初始化 class。

而且您不需要这些 'DemandCabRepository'。所有的工作都由 Doctrine 完成

我可以重现你的问题,但我不确定你的情况是否如此。

无论如何,我的假设是您在查询构建器的帮助下至少查询一次与 decision 关系连接的 demand 实体.也许这是在您的操作、事件侦听器或代码中的其他地方完成的。

所以你可能有这样的东西:

$qb = $this->getDoctrine()
        ->getRepository(DemandCab::class)->createQueryBuilder("dem");
$qb->select('dem, dec');
$qb->leftJoin("dem.decisionsCab", "dec");

$qb->andWhere("dec.decision IS NULL");
$qb->orderBy("dem.startDate", "DESC");

$results = $qb->getQuery()->getResult(); // <-- the decisionsCab collection is hydrated but filtered

$qb2 = $this->getDoctrine()
        ->getRepository(DemandCab::class)->createQueryBuilder("dem");
$qb2->select('dem, dec');
$qb2->leftJoin("dem.decisionsCab", "dec");

$qb2->andWhere("dem.completed = 1");
$qb2->orderBy("dem.startDate", "DESC");

    $q = $qb2->getQuery();
    //$q->setHint(Query::HINT_REFRESH, true);

    $results = $q->getResult();

问题出在 Doctrine\ORM\Internal\Hydration\ObjectHydrator,它有 属性“initializedCollections”,其中已经初始化了集合保留并且集合由父实体类型和实体本身散列。不幸的是,在上述情况下,heydrator 不了解集合在第一个查询中被过滤并在第二个查询中使用它以避免再水化。(github link)

解决方案 是使查询构建器刷新。试试代码:

$qb->orderBy("dem.startDate", "DESC");
$q = $qb->getQuery();
$q->setHint(Query::HINT_REFRESH, true);    // <-- Tell the hydrator to refresh
return $q->getResult();