2015-02-23 2 views
6

Я работаю над проектом symfony 2.5 с доктриной 2.4.Как кэшировать доктрину «findOneBy()» с ключом кеша и временем ожидания кеша в Symfony 2.4?

Я хочу кэшировать результат запроса с идентификатором кэша и временем кеша, поэтому я могу удалить результат кэша, когда это необходимо, хотя администратор.

Я могу кэшировать результат запроса с помощью опции «createQueryBuilder()».

Пример:

$this->createQueryBuilder('some_table') 
        ->select('some_table') 
        ->where('some_table.deleted_date IS NULL') 
        ->getQuery() 
        ->useResultCache(true) 
        ->setResultCacheLifetime(120) //Query Cache lifetime 
        ->setResultCacheId($queryCacheId) //Query Cache Id 
        ->getResult(); 

Но я не могу найти подобный способ chache результат запроса для ") findOneBy (" вариант.

Пример:

$this->findOneBy(array('some_field'=>$some_value)); 

Я ищу какой-то правильное решение, любая помощь очень ценится.

+1

https://groups.google.com/d/msg/doctrine-user/RIeH8ZkKyEY/HnR7h2p0lCQJ Как говорит Ocramius, вы nedd переопределить этот метод в репо, если вы хотите воспользоваться преимуществами кэширования операций. – DonCallisto

+0

Спасибо за ваш ответ. Позвольте мне попробовать и спросим вас, если потребуется. –

+0

Это, как я переопределить функцию "findOneBy" в классе хранилища общественная функция findOneBy (массив $ criteria_array) { \t \t $ запрос = $ this-> createQueryBuilder ('б') -> выберите ('б'); \t \t Еогеасп ($ criteria_array, как $ FIELDNAME => $ критериев) { \t \t \t $ query-> andWhere ("Ь $ FIELDNAME =:. $ FIELDNAME"); \t \t \t $ query-> setParameter ("$ fieldName", $ criteria); \t \t} \t \t возвращение $ query-> GetQuery() \t \t \t -> useResultCache (истина) \t \t \t -> setResultCacheLifetime (120) \t \t \t -> setResultCacheId ($ queryCacheId) \t \t \t -> GetResult(); } Проверьте и исправьте меня. Нужно ли переопределять функцию «Найти *» во всем репозитории всякий раз, когда мне нужно кэшировать результат? –

ответ

2

Вы должны пересмотреть все findBy * или findOneBy * функция в пользовательском хранилище: это единственный способ, как поведение по умолчанию doctrine2 не принимает во внимание эта ситуация. До вас, к сожалению.

Также Ocramius (а Doctrine2 разви) сказать, что здесь https://groups.google.com/d/msg/doctrine-user/RIeH8ZkKyEY/HnR7h2p0lCQJ

0

Сделать общую функцию для этого.

$repo->findOneByYourSufff($yourStuff, $yourRepoClass); 

Вслед за вашей общей функцией:

public function findOneByYourSufff($yourStuff, $yourRepoClass) { 


     $q = $this->createQueryBuilder() 
       ->select('x.*') 
       ->from($yourRepoClass, 'x'); 

       foreach($yourStuff as $fieldKey => $wh) { 
        $q->andWhere("b.$fieldKey = :fieldName"); 
        $q->setParameter("fieldName", $wh); 
       } 

      $q->useResultCache(true) 
       ->setResultCacheLifetime(120) //Query Cache lifetime 
       ->setResultCacheId($queryCacheId) //Query Cache Id 
       ->getSingleResult(); 

    return $q 

} 
+0

Это не решение: '$ yourStuff' может быть массивом, как вы справляетесь с этим делом? – DonCallisto

+0

вы можете положить -> где ('x.yourStuff =?', $ YourStuff) в цикле. Подготовьте свой массив в своей логической функции. –

+0

Во-первых, это не так «легко» (вы должны использовать 'andWhere()' [в вашем цикле]), во-вторых, ваш ответ не подчеркивал, что для меня это не очень хороший ответ. Обновите его – DonCallisto

0

Вот пример того, как можно кэшировать результаты из одного хранилища для функций:

  • findOneBy(['foo' => 'bar'])
  • findOneByFoo('bar')
  • findOneBy(['bar' => 'foo', 'foo' => 'bar')
  • и т.д.

Он отменяет функцию EntityRepository::FindOneBy. Он следует одной и той же сигнатуре, поэтому нет необходимости обновлять вызывающий код. Все вызовы типа FindOneBy% пройдут через нашу реализацию findOneBy.

<?php 
/** 
* MyObject Repo  
*/ 

namespace MyLib\Entity\Repository; 
use Doctrine\ORM\EntityRepository; 

class MyObjectRepository extends EntityRepository 
{ 

    const CACHE_KEY = 'my_object'; 
    const ALIAS = 'my_object'; 

    /** 
    * Override - use cache. 
    * 
    * @param array $criteria 
    * @param array|null $orderBy 
    * @return mixed 
    */ 
    public function findOneBy(array $criteria, array $orderBy = null) 
    { 
     $queryBuilder = $this->createQueryBuilder(self::ALIAS); 
     foreach($criteria as $field => $value) { 
      $queryBuilder->andWhere(self::ALIAS . ".{$field} = :{$field}")->setParameter($field, $value); 
     } 
     if (is_array($orderBy)) { 
      foreach ($orderBy as $field => $dir) { 
       $queryBuilder->addOrderBy($field, $dir); 
      } 
     } 
     $queryBuilder->setMaxResults(1); 

     $query = $queryBuilder->getQuery(); 

     $query->useResultCache(true, 3600, self::CACHE_KEY); 

     $result = $query->getResult(); 

     if ($result) return reset($result); 

     return $result; 
    } 

    /** 
    * Depending how you hydrate the entities may make more 
    * sense to use cache layer at findAll 
    * 
    * @param void 
    * @return array The entities. 
    */ 
    public function findAll() 
    { 
     $query = $this->getEntityManager()->createQuery('select v from \OAS\Entity\MyObject v'); 

     $query->useResultCache(true, 3600, self::CACHE_KEY); 

     $result = $query->getResult(); 

     return $result; 
    } 

    /** 
    * 
    */ 
    public function invalidateCache() 
    { 
     //this would depend on your cache implementation... 
     $container = \Zend_Registry::get('doctrine'); 

     $cache = $container->getCacheInstance(); 

     $cache->delete(self::CACHE_KEY); 
    } 
} 

Это может быть сделано в более стиле ООП, конечно, расширяя промежуточный класс, если вы хотите сказать, есть свойство на хранилище, которое просто превратило кэш включен или выключен. Вы можете расширить аналогичный подход для других операций с операциями репозитория.

+0

Неправильная реализация. У вас будет один кеш для всех запросов. 'findOneBy (['name' => 'foo'], ['name' => 'asc']) === findOneBy (['title' => 'foo'], ['title' => 'desc' ]) === findAll() ' – ghost404

+0

@ ghost404 Если я понимаю, что вы говорите, что вы ошибаетесь. Кэш второго уровня Doctrine осведомлен о запросе. См. '$ Querykey', полученный из хеша объекта запроса в реферате. По крайней мере, по крайней мере. Сейчас у меня код, похожий на годы. – ficuscr

+1

Вы правы. Я допустил ошибку. – ghost404

Смежные вопросы