У меня есть это лицо:
/** * User state. * * @ORM\Entity(repositoryClass="User\Repository\StateRepository") * @ORM\Table(name="user_state") */ class State implements StateInterface { /** ONE-TO-ONE BIDIRECTIONAL, OWNING SIDE * @var User * @ORM\Id * @ORM\OneToOne(targetEntity="User\Entity\User", inversedBy="state") * @ORM\JoinColumn(name="user_id", referencedColumnName="id") */ protected $user; /** ONE-TO-ONE UNIDIRECTIONAL * @var \Application\Entity\State * @ORM\Id * @ORM\ManyToOne(targetEntity="Application\Entity\State", fetch="EAGER") * @ORM\JoinColumn(name="state_id", referencedColumnName="id") */ protected $state; public function __construct(User $user, \Application\Entity\State $state) { $this->user = $user; $this->state = $state; } /********/ /* USER */ /********/ /** * Get user * * @return User */ public function getUser() { return $this->user; } /** * Set user * * @param User $user * * @return Email */ public function setUser(User $user) { $this->user = $user; return $this; } /**********/ /* STATUS */ /**********/ /** * Get state * * @return \Application\Entity\State */ public function getState() { return $this->state; } /** * Set state * * @param \Application\Entity\State $state * * @return State */ public function setState(\Application\Entity\State $state) { $this->state = $state; return $this; } /******/ /* ID */ /******/ /** * Get id. * * @return int */ public function getId() { return $this->state->getId(); } /** * Set id. * * @param int $id * * @return State */ public function setId($id) { $this->state->setId((int) $id); return $this; } /********/ /* NAME */ /********/ /** * Get name * * @return string */ public function getName() { return $this->state->getName(); } /** * Set name * * @param string $name * * @return State */ public function setName($name) { $this->state->setName((string) $name); return $this; } }
И чтобы получить объект, я делаю это в своем настраиваемом репозитории
return self::findOneBy($params);
Что приводит к этому запросу:
SELECT t0.user_id AS user_id1, t0.state_id AS state_id2, t3.id AS id4, t3.name AS name5 FROM user_state t0 LEFT JOIN state t3 ON t0.state_id = t3.id WHERE t0.user_id = ? LIMIT 1
Отлично! Именно то, что я хотел, и связанная с ним организация с нетерпением вызвана из-за fetch="EAGER"
в отношении. Теперь я хочу сделать то же самое с DQL, поэтому я делаю это:
$query = $this->_em->createQuery("SELECT us, s FROM 'User\Entity\State' us LEFT JOIN us.state s WHERE us.user = :user_id"); $query->setParameters($params); $query->setFetchMode('User\Entity\State', 'state', ClassMetadata::FETCH_EAGER); return $query->getOneOrNullResult();
Я получаю сообщение об ошибке: Call to a member function getId() on a non-object
По Call to a member function getId() on a non-object
видимому, связанный объект неправильно загружен. Когда я проверяю вручную, $state
оказывается равным NULL
Если я опускаю s в запросе следующим образом:
$query = $this->_em->createQuery("SELECT us FROM 'User\Entity\State' us LEFT JOIN us.state s WHERE us.user = :user_id");
Затем он возвращает результат точно так, как я его хочу, но он приводит к двум запросам (дополнительный запрос для получения связанного объекта состояния), что, очевидно, имеет смысл, потому что запрос больше не рассматривается как соединение для fetch join
, поэтому его ленивые нагрузки связанного с ним.
Как я могу получить тот же результат (один запрос, один результат), как я получил с помощью метода findOneBy
но с использованием DQL?
Я только что обновил свой Doctrine2 ORM до версии 2.5 и теперь он работает 🙂
Элементы Doctrine внутри моего текущего файла composer.json выглядят следующим образом:
"doctrine/doctrine-module":"dev-master", "doctrine/doctrine-orm-module": "dev-master", "doctrine/dbal": "2.5.*@dev", "doctrine/orm": "2.5.*@dev",