Оживляем Doctrine 2 Document/Entity при получении из кэша
Недавно столкнулись на работе с такой проблемой. При получении объекта (Doctrine 2 Document) из кэша все методы, которые у него вызываются, возвращают пустое значение. Особенно интересно было смотерть на это, когда ttl кэша был 10 секунд, и при обновлении страницы результаты то были, то пропадали.
Задача
Ну, например, есть у нас объект Пользователь. А у него есть связанные с ним объекты книг. При этом вызывая метод $user->getBooks() в случае, когда объекта “свежий” (т.е. его нет в кэше) – мы получаем книги. А вот когда для следующего запроса он берется из кэша – то возвращается NULL. Почему так происходит?
Объяснение
Проблема в том, что такой объект – “мертвый”, а именно он находится в состоянии DETACHED в DocumentManager/EntityManager и работать с его связями не получится. Но выход есть.
Решение
Можно “оживить” его, а именно приаттачить к текущему экземпляру DocumentManager/EntityManager, так, чтобы он стал в состояние MANAGED. Для этого есть функция merge.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/** * Merges the state of a detached document into the persistence context * of this DocumentManager and returns the managed copy of the document. * The document passed to merge will not become associated/managed with this DocumentManager. * * @param object $document The detached document to merge into the persistence context. * @return object The managed copy of the document. */ public function merge($document) { if (!is_object($document)) { throw new \InvalidArgumentException(gettype($document)); } $this->errorIfClosed(); return $this->unitOfWork->merge($document); } |
Для этого выполняем такую команду:
1 |
$user = $this->_dm->merge($user); |
$this->_dm – это экземпляр DocumentManager.
Резюме
После получения Doctrine Document/Entity из кэша обязательно делаем ему merge!