如何在 Symfony 2.4 中使用缓存 ID 和缓存生命周期选项缓存学说 "findOneBy()" 查询?

How to cache doctrine "findOneBy()" query with cache id and cache lifetime option in Symfony 2.4?

我正在使用 doctrine 2.4 开发 symfony 2.5 项目。

我想用缓存 ID 和缓存时间来缓存查询结果,这样我就可以在需要时通过管理员删除缓存结果。

我可以使用 "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();

但是我找不到类似的方法来为 "findOneBy()" 选项查询查询结果。

示例:

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

我正在寻找一些合适的解决方案,非常感谢任何帮助。

为此创建一个通用函数。

 $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

 }

您需要将每个 findBy* 或 findOneBy* 函数重新定义到自定义存储库中:这是唯一的方法,因为 doctrine2 默认行为没有考虑到这种情况。 不幸的是,由你决定。

还有 Ocramius(一个 Doctrine2 开发者)在这里说 https://groups.google.com/d/msg/doctrine-user/RIeH8ZkKyEY/HnR7h2p0lCQJ

这是一个示例,说明如何从函数的单个存储库中缓存结果:

  • 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);
    }
}

这当然可以以更面向对象的方式完成,扩展一个中介 class,如果你想说在存储库上有一个 属性,它只是打开或关闭缓存。您可以为其他存储库操作功能扩展类似的方法。