В чем причина того, что отношения OneToOne в Doctrine не могут быть загружены лениво? - PullRequest
0 голосов
/ 12 ноября 2018

У меня есть Person и Admin сущность. Один Person может иметь только один Admin, но мне не нужен админ все время. Когда я перечислю всех людей, связанных с администратором, doctrine загрузит всех администраторов из БД. Почему это происходит?

1 Ответ

0 голосов
/ 12 ноября 2018

В случае связи один-к-одному (и в аналогичных случаях, например, при ленивой загрузке ассоциации один-ко-многим) Doctrine генерирует так называемые прокси-объекты для связанных объектов.Эти прокси-объекты имитируют интерфейс целевой сущности, но только запускают фактическую загрузку данных из базы данных при доступе к полю non-id .

Из-за этого в вашем случае, когда вы выбираете список Person сущностей - вы не получаете список Admin сущностей, извлеченных из базы данных, но вместо этого получаете список Admin прокси.Если вы не будете (время от времени или намеренно) пытаться получить доступ к некоторым свойствам сущности Admin (за исключением ее id, к которому можно безопасно обращаться), Doctrine не будет пытаться получить любую информацию Admin из базы данных.

Рассмотрим следующую упрощенную настройку A и B сущностей с однозначной ассоциацией:

// A.php

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity()
 */
class A
{
    /**
     * @var integer
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var B
     * @ORM\OneToOne(targetEntity="App\Entity\B")
     */
    private $b;

    /**
     * @return int
     */
    public function getId(): int
    {
        return $this->id;
    }

    /**
     * @return B
     */
    public function getB(): B
    {
        return $this->b;
    }
}

// B.php

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity()
 */
class B
{
    /**
     * @var integer
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var string|null
     * @ORM\Column(type="string", nullable=true)
     */
    private $name;
}

Вы можете доказать, что A::$b содержит прокси-объект, посмотрев в отладчик илииспользуя отражение:

$entities = $this->getEntityManager()->getRepository(\App\Entity\A::class)->findAll();
/** @var \App\Entity\A $a */
$a = array_shift($entities);
$class = (new \ReflectionObject($a->getB()))->getName();

В этом случае значение переменной $class будет Proxies\__CG__\App\Entity\B (прокси-объект Doctrine для App\Entity\B), а не App\Entity\B, как это было бы в случае нормальной сущностиобъект.

...