【问题标题】:Doctrine - OneToMany relation, all result row doesn't fetch in objectDoctrine - OneToMany 关系,所有结果行不获取对象
【发布时间】:2018-01-08 14:45:59
【问题描述】:

我尝试获取我的所有对象 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 个决定...

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

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

谢谢

【问题讨论】:

  • 您使用的是哪个学说版本?
  • 我使用的是 Doctrine 2.6 版
  • 您还可以为您的实体添加所有字段吗?其中之一可能是水合不当的原因。

标签: php symfony doctrine hydration


【解决方案1】:

我能够重现您的问题,但我不确定这是否是您的情况。

无论如何,我的假设是您在查询构建器的帮助下至少查询一次与 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();

【讨论】:

  • 你是最棒的!谢谢;)
【解决方案2】:

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

而且您不需要任何“DemandCabRepository”。所有工作都由 Doctrine 完成

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多