Я использую расширения Gedmo Doctrine
Пока все работает хорошо, кроме кэширования переводов.
$entity = $repository ->findByIdFullData($id) ->setHint(\Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER, 'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker') ->useResultCache(true, $cache_time, $cache_name) ->getOneOrNullResult();
findByIdFullData()
возвращает \Doctrine\ORM\Query
Но переводы не кэшируются. В профилировщике я вижу такие запросы:
SELECT e0_.content AS content0, e0_.field AS field1 FROM ext_translations e0_ WHERE e0_.foreign_key = ? AND e0_.locale = ? AND e0_.object_class = ?
И все запросы в профилировщике – это получить результаты от ext_translations
. Как я могу кэшировать результат уже с переведенными строками?
Пробовал использовать Array Hydration и memCache, но закончил испортить больше, потому что в моем результирующем элементе загружен медиафайл, который не может быть сериализован или что-то еще. В любом случае, я бы переписал большую часть кода.
Любая помощь приветствуется.
Изменить :
Я пробовал ответ Кароля Войцеховского и решил часть проблемы. Он кэшируется, когда я использую getOneOrNullResult()
но не с getResult()
. Вот какой код.
В сервисе:
$query = $this->em ->getRepository('MainBundle:Channels') ->findActiveChannelsByGroupId($id); $this->container->get('my.translations')->addTranslationWalkerToQuery($query, $this->request); $channels = $query ->useResultCache(true, 900, '1__channels__active_by_group_1') ->getResult();
Канальный репозиторий:
public function findActiveChannelsByGroupId($group_id, $limit = null) { $rs = $this ->createQueryBuilder('c') ->select('c', 'm') ->leftJoin('c.media', 'm') ->leftJoin('c.group', 'g') ->where('c.active = 1') ->andWhere('g.id = :group_id') ->orderBy('c.sortOrder', 'asc') ->setParameter('group_id', $group_id) ->setMaxResults($limit); return $rs->getQuery(); }
Если я findActiveChannelsByGroupId($id, 1)
на findActiveChannelsByGroupId($id, 1)
(параметр ограничения уведомления), он все равно не кэширует, но если я getOneOrNullResult()
на getOneOrNullResult()
, запрос будет кэшироваться
Наш рабочий код:
public function addTranslationWalkerToQuery($query, $request) { $config = $this->container->get('doctrine')->getManager()->getConfiguration(); if ($config->getCustomHydrationMode(TranslationWalker::HYDRATE_OBJECT_TRANSLATION) === null) { $config->addCustomHydrationMode( TranslationWalker::HYDRATE_OBJECT_TRANSLATION, 'Gedmo\\Translatable\\Hydrator\\ORM\\ObjectHydrator' ); } $query->setHint( \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER, 'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker' ); $query->setHint( \Gedmo\Translatable\TranslatableListener::HINT_TRANSLATABLE_LOCALE, $request->getLocale() // take locale from session or request etc. ); $query->setHydrationMode(TranslationWalker::HYDRATE_OBJECT_TRANSLATION); $query->setHint(Query::HINT_REFRESH, true); }
EDIT: И если вы хотите «getResult»,
Выполнение getResult изменяет режим гидратации. Посмотрите на метод класса AbstractQuery:
/** * Gets the list of results for the query. * * Alias for execute(null, $hydrationMode = HYDRATE_OBJECT). * * @param int $hydrationMode * * @return array */ public function getResult($hydrationMode = self::HYDRATE_OBJECT) { return $this->execute(null, $hydrationMode); }
Он работает с getOneOrNullResult
потому что он не меняет режим гидратации
public function getOneOrNullResult($hydrationMode = null)
Если вы хотите кэшировать переводимые запросы, вы должны изменить режим гидратации во время выполнения метода getResult для TranslationWalker::HYDRATE_OBJECT_TRANSLATION
.
Лично я включу этот метод в сервис, который будет обрабатывать все, что связано с переводами.