Skip to content

Instantly share code, notes, and snippets.

@aramalipoor
Last active August 29, 2015 14:22
Show Gist options
  • Save aramalipoor/6e67bc6c3d936428661e to your computer and use it in GitHub Desktop.
Save aramalipoor/6e67bc6c3d936428661e to your computer and use it in GitHub Desktop.
Symfony2 Container Cache Invalidator
<?php
namespace Sylius\Bundle\ThemeBundle\DependencyInjection;
use Sylius\Bundle\ThemeBundle\EventSubscriber\ContainerInvalidatorEventSubscriber;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface;
class ContainerInvalidator
{
/**
* @var Filesystem
*/
private $filesystem;
/**
* @var CacheClearerInterface
*/
private $cacheClearer;
/**
* @var ContainerInvalidatorEventSubscriber
*/
private $containerInvalidatorSubscriber;
/**
* @var EventDispatcherInterface
*/
private $eventDispatcher;
/**
* @var bool
*/
private $manipulated = false;
/**
* Constructor.
*
* @param Filesystem $filesystem
* @param CacheClearerInterface $cacheClearer
* @param ContainerInvalidatorEventSubscriber $containerInvalidatorSubscriber
* @param EventDispatcherInterface $eventDispatcher
* @param string $cacheDir
*/
public function __construct(
Filesystem $filesystem,
ContainerInvalidatorEventSubscriber $containerInvalidatorSubscriber,
CacheClearerInterface $cacheClearer,
EventDispatcherInterface $eventDispatcher,
$cacheDir
) {
$this->filesystem = $filesystem;
$this->cacheClearer = $cacheClearer;
$this->containerInvalidatorSubscriber = $containerInvalidatorSubscriber;
$this->eventDispatcher = $eventDispatcher;
$this->cacheDir = $cacheDir;
}
/**
* When themes are enabled/disabled we need to invalidate the
* container's cache so that it will be compiled on next request.
* TODO Implement an optional warmup routine.
*
* You shall not use this method directly unless you're on termination phase.
*/
public function invalidateCache()
{
$this->cacheClearer->clear($this->cacheDir);
$this->filesystem->remove($this->cacheDir);
}
/**
* Returns if parameters has been manipulated in this session.
*/
public function isManipulated()
{
return $this->manipulated;
}
/**
* Sets manipulated flag to true. Use this to tell the invalidator listener
* to clear the cache on termination.
*/
public function setManipulated()
{
if (!$this->manipulated) {
// This is the first time so add appropriate event subscriber to kernel.terminate event.
$this->eventDispatcher->addSubscriber($this->containerInvalidatorSubscriber);
}
$this->manipulated = true;
}
}
<?php
namespace Sylius\Bundle\ThemeBundle\EventSubscriber;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Invalidates container cache on termination if container is flagged as manipulated.
*/
class ContainerInvalidatorSubscriber implements EventSubscriberInterface
{
/**
* @var ContainerInterface
*/
private $container;
/**
* Constructor.
*
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/**
* @param PostResponseEvent $event
*/
public function onTerminate(PostResponseEvent $event)
{
$invalidator = $this->container->get('sylius.theme.container_invalidator');
if ($invalidator->isManipulated()) {
$invalidator->invalidateCache();
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return array(
KernelEvents::TERMINATE => 'onTerminate',
);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<!-- Dependency Injection -->
<parameter key="sylius.theme.container_invalidator.class">Sylius\Bundle\ThemeBundle\DependencyInjection\ContainerInvalidator</parameter>
<!-- Event Listeners -->
<parameter key="sylius.theme.container_invalidator_subscriber.class">Sylius\Bundle\ThemeBundle\EventSubscriber\ContainerInvalidatorSubscriber</parameter>
</parameters>
<services>
<!-- Dependency Injection -->
<service id="sylius.theme.container_invalidator" class="%sylius.theme.container_invalidator.class%">
<argument type="service" id="filesystem" />
<argument type="service" id="sylius.theme.container_invalidator_subscriber" />
<argument type="service" id="cache_clearer" />
<argument type="service" id="event_dispatcher" />
<argument>%kernel.cache_dir%</argument>
</service>
<!-- Event Subscribers -->
<service id="sylius.theme.container_invalidator_subscriber" class="%sylius.theme.container_invalidator_subscriber.class%">
<argument type="service" id="service_container" />
<!-- Will be registered on event_dispatcher by invalidator service -->
</service>
</services>
</container>
@aramalipoor
Copy link
Author

Usage would be very easy:

# Inject sylius.theme.container_invalidator and then 
# call method below whenever you need the container to be invalidated and re-compiled.
$this->containerInvalidator->setManipulated();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment