Отношение Doctrine - OneToMany, все строки результата не извлекаются в объекте

Я пытаюсь получить все мои объекты 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

Мои данные DemandCab

Мои данные DecisionCab

Когда я сбрасываю результат, появляются только 2 решения...

... тогда как, когда я использую getArrayResultУ меня есть 4 решения...

Запрос хороший, но я не понимаю, почему гидратация удаляет объект DecisionCab с атрибутом decision в 0 или 1 (отображается только ноль).

Я хотел бы понять, почему и есть ли решение получить объект DemandCab со всеми дочерними объектами DecisionCab.

Спасибо

2 ответа

Решение

Я могу воспроизвести вашу проблему, но я не уверен, что это ваш случай.

В любом случае, я предполагаю, что вы запрашиваете сущность по требованию, соединенную с отношением принятия решения хотя бы один раз, с помощью построителя запросов. Может быть, это делается в ваших действиях, в слушателе событий или где-то еще в вашем коде.

Таким образом, вы можете иметь что-то вроде:

$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", где хранятся уже инициализированные коллекции, и коллекции хешируются по типу родительской сущности и самой сущности. К сожалению, в приведенном выше случае, Гейдратор не понимает, что коллекция фильтруется в 1-м запросе, и использует его во 2-м запросе, чтобы избежать повторной гидратации ( ссылка на github).

Решение состоит в том, чтобы заставить построитель запросов обновить. Попробуйте код:

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

Сначала вы инициализируете свой класс отношением ManyToOne с ArrayCollection.

И вам не нужно ничего из этого 'DemandCabRepository'. Вся работа выполнена доктриной

Другие вопросы по тегам