Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Added basic comprobation to check valid entity keys.
<?php
namespace MyVendor\MyBundle\Cache;
/**
* Better than using
* $this->getDoctrine()->getManager()->getConfiguration()->getResultCacheImpl()->delete(...);
* in your controllers
*/
use Doctrine\ORM\Event\OnFlushEventArgs;
use Symfony\Component\DependencyInjection\ContainerAware;
use \LogicException;
class CacheInvalidator extends ContainerAware
{
protected $cacheIds = array();
public function __construct()
{
$this->cacheIds = $this->getCacheIds();
foreach ($this->cacheIds as $className => $config) {
if (!class_exists($className)) {
throw new LogicException(sprintf('Class %s does not exist and could not be loaded', $className));
}
}
}
public function onFlush(OnFlushEventArgs $eventArgs)
{
$em = $eventArgs->getEntityManager();
$uow = $em->getUnitOfWork();
// $uow->getScheduledCollectionDeletions()
// $uow->getScheduledCollectionUpdates()
$scheduledEntityChanges = array(
'insert' => $uow->getScheduledEntityInsertions(),
'update' => $uow->getScheduledEntityUpdates(),
'delete' => $uow->getScheduledEntityDeletions()
);
$cacheIds = array();
foreach ($scheduledEntityChanges as $change => $entities) {
foreach ($entities as $entity) {
$cacheIds = array_merge($cacheIds, $this->getCacheIdsForEntity($entity, $change));
}
}
if (count($cacheIds) == 0) {
return;
}
$cacheIds = array_unique($cacheIds);
$resultCache = $em->getConfiguration()->getResultCacheImpl();
array_map(array($resultCache, 'delete'), $cacheIds);
}
protected function getCacheIdsForEntity($entity, $change)
{
$className = get_class($entity);
if (!array_key_exists($className, $this->cacheIds)) {
return array();
}
$parsedCacheIds = array();
foreach ($this->cacheIds[$className] as $cacheId) {
if (!isset($cacheId['change'])) {
$cacheId['change'] = 'any';
}
$cacheId['change'] = strtolower($cacheId['change']);
if ($cacheId['change'] != $change && $cacheId['change'] != 'any') {
continue;
}
if ($parsedId = $this->parseCacheId($cacheId, $entity)) {
$parsedCacheIds[] = $parsedId;
}
unset($parsedId);
}
return $parsedCacheIds;
}
protected function parseCacheId(array $cacheId, $entity)
{
if (!array_key_exists('id', $cacheId)) {
return false;
}
if (!array_key_exists('vars', $cacheId)) {
return $cacheId['id'];
}
$parsedVars = array();
foreach ($cacheId['vars'] as $var) {
if (!isset($var['value'])) {
continue;
}
if (!isset($var['type'])) {
$var['type'] = '';
}
$parsedVars[] = $this->resolveVar($var['value'], $var['type'], $entity);
}
return vsprintf($cacheId['id'], $parsedVars);
}
protected function resolveVar($value, $type, $entity) {
if ($type != 'method') {
return $value;
}
$methodStr = $value;
$checkEntityMethod = function($obj, $method) use ($methodStr) {
if (!method_exists($obj, $method)) {
throw new LogicException(sprintf('%s is not a valid method', $methodStr));
}
return $obj->{$method}();
};
if (!strstr($methodStr, '.')) {
return $checkEntityMethod($entity, $methodStr);
}
$methods = explode('.', $methodStr);
$numMethods = count($methods);
$resolvedValue = $entity;
for ($i = 0; $i < $numMethods; $i++) {
$resolvedValue = $checkEntityMethod($resolvedValue, $methods[$i]);
}
return $resolvedValue;
}
protected function getCacheIds()
{
return array(
'MyVendor\\MyBundle\\Entity\\User' => array(
array(
'id' => 'user_%d',
'vars' => array(
array(
'value' => 'getId',
'type' => 'method',
),
),
'change' => 'any',
),
),
// Add more entities etc here
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.