And*_*iev 8 php orm caching doctrine-orm
我很多时候都在解决这个问题,并且发现,正式地说,我只能缓存一些自定义查询(在Query对象上使用resultResultCache(true)).但我需要将我的应用程序中的每个查询缓存到某个表中.那么在EntityManager上查找*方法呢?...
有人可以帮我找到一个优雅的解决方案吗?
Ocr*_*ius 12
目前尚不支持此功能,您最终应该在服务层或扩展存储库中处理它.
您正在寻找的是Hibernate中的二级缓存,它基本上允许您插入一个键值存储,如redis,riak,mongodb等,以便在操作简单的获取操作时快速实现.
在https://github.com/doctrine/doctrine2/pull/580上有一项正在进行中的工作请求,这可能会在Doctrine ORM 2.5中出现,所以请查看那个.
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\EntityManager;
use Doctrine\Common\Cache\Cache;
use Doctrine\Common\Cache\ArrayCache;
class MyBaseRepo extends EntityRepository
{
public function __construct(EntityManager $entityManager)
{
parent::__construct($entityManager);
$cache = $em->getConfiguration()->getHydrationCache();
$this->cache = $cache ?: new ArrayCache();
}
public function find($id)
{
if (!$object = $this->tryFetchFromCache($id)) {
$object = parent::find($id);
$this->cache->save($this->generateKey($id), $object);
}
return $object;
}
protected function tryFetchFromCache($id)
{
if (!$object = $this->cache->fetch($this->generateCacheKey($id))) {
return null;
}
return $this->getEntityManager()->merge($object);
}
public function generateCacheKey($id) { /* ... */ }
}
Run Code Online (Sandbox Code Playgroud)
在引导应用程序时,您可以强制将其作为配置中ORM的基本存储库:
$configuration = new \Doctrine\ORM\Configuration();
$configuration->setDefaultRepositoryClassName('My\MyBaseRepo');
Run Code Online (Sandbox Code Playgroud)
当您的任何实体发生更新/保存时,这也会强制您清除缓存条目:
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Events;
class IssueUpdateSubscriber implements EventSubscriber
{
public function onFlush(OnFlushEventArgs $args)
{
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
if (!$cache = $em->getConfiguration()->getHydrationCache()) {
return;
}
$busted = array_merge(
$uow->getScheduledEntityUpdates(),
$uow->getScheduledEntityDeletions(),
);
foreach ($busted as $entityToClear) {
$className = get_class($entityToClear);
$metadata = $em->getClassMetadata($className);
$repository = $em->getRepository($className);
$id = $metadata->getIdentifierValues($entityToClear);
$cache->delete($repository->generateCacheKey($id));
}
}
public function getSubscribedEvents()
{
return array(Events::onFlush);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,此实现不会拦截对给定实体的数据库的所有访问.它不会拦截由代理引起的延迟加载初始化,而且它非常脆弱,所以请设置一些适当的集成测试来支持它.