Особенности PARTIAL DQL запросов в Doctrine

// Декабрь 28th, 2017 // Doctrine 2, PHP

medium_logo_doctrineИногда у вас может возникнуть ситуация, когда вроде бы при нормальном DQL-запросе объект почему-то грузится не весь. Ну т.е. запрос проходит стадию преобразования из DQL в SQL, выполняется, потом обратно идёт гидрация в объект, а части данных то и нет — отсутствуют некоторые поля, котоыре есть а базе данных. Вы конечно пробуете отключить все кэши, сбрасываете их по 10 раз, а толку ноль. Разгадка тут проста. Если в течении одного HTTP-запроса вы используете PARTIAL-запрос, то потом для всех следующих запросов в которые попадает этот объект по IDENITY-MAP он уже не грузится из БД, а берется из неё.

identity-map

Пример

Пусть у нас есть модель User с полями id, username, name.

Грузим её через QueryBuilder.

$qb = $this->em->createQueryBuilder();
$qb->select('PARTIAL u.{id, username}')
->from(User::class, 'u')
->where('u.id = :id')
->setParameter(':id', $id);
$user = $qb->getQuery()->getResult();

Потом мы в другом куске кода захотели загрузить юзера полностью.

$qb->select('u')
->from(User::class, 'u')
->where('u.id = :id')
->setParameter(':id', $id);
$user = $qb->getQuery()->getResult();

При это окажется, что user->getName равен null. В такой ситуации есть два выхода :-) Первый — делать полную перезагрузку модели из БД.

$this->em->refresh($user);

Но если таких моделей много, это чревато большой нагрузкой на базу. Второй вариант — использовать специальный HINT, который скажет Doctrine, что надо обращаться к базе, вместо использования IDENTITY MAP.

$user = $qb->getQuery()->setHint(Query::HINT_REFRESH, true)->getResult();
Share

Спасибо!


Если вам помогла статья, или вы хотите поддержать мои исследования и блог - вот лучший способ сделать это:


Комментировать