This bundle makes two changes to Symfony2's default HTTP cache (currently supporting Symfony versions 2.1 to 2.2):
- Allows parts of a view to be cached through ESI, even if the master response
has a "private" Cache-Control header (Symfony2 will be default force the
entire response to be public). This replicates the
sf_cache_key
behaviour of Symfony of 1.4 which allowed for easy partial caching. (Important: Use release 0.1.1 if you want this feature. It has been removed from later versions, as Symfony now supports it out of the box). - Makes it possible to use ESI within JSON responses
Disclaimer: Please only use this bundle if you have a solid understanding of ESI caching, as it removes some of the safeguards put in place by default with Symfony2. If you were to, for example, include a user's private content via ESI without a cache key that's unique to them, that content is likely to leak through to other users.
Start by enabling Symfony2's HttpCache and ESI support as per the Symfony2 docs:
- http://symfony.com/doc/current/book/http_cache.html#symfony2-reverse-proxy
- http://symfony.com/doc/current/book/http_cache.html#using-esi-in-symfony2
Add the bundle to composer.json
"require": {
// ...
"jamesi/http-cache-bundle": "dev-master@dev"
}
Update the packages through composer:
$ php composer.phar update
Add the bundle in the kernel:
<?php
// app/AppKernel.php
public function registerBundles()
{
$bundles = array(
// ...
new Jamesi\HttpCacheBundle\JamesiHttpCacheBundle(),
);
}
Add the following to parameters.yml:
parameters:
# ...
esi.class: Jamesi\HttpCacheBundle\HttpCache\Esi
<?php
// app/AppCache.php
require_once __DIR__.'/AppKernel.php';
// use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache;
use Jamesi\HttpCacheBundle\HttpCache\HttpCache;
class AppCache extends HttpCache
{
}
<?php
// Controller.php
<?php
public function indexAction()
{
return $this->render('index.html.twig');
}
public function componentAction()
{
$response = new Response();
$response->setSharedMaxAge(600);
return $this->render('_component.html.twig', array(), $response);
}
{# index.html.twig #}
{% render 'component' with {}, {'standalone': true} %}
If the bundle is configured correctly, the master response won't have a public Cache-Control header, and the "component" response will have been cached and served via ESI.
Cache keys can be passed in via the first set of parameters, which cause ESI to store/retrieve a unique response:
{# Symfony 2.1 style #}
{% render 'component' with {'user_id': id}, {'standalone': true} %}
{# Symfony 2.2+ style #}
{{ render_esi(controller('..:component', { 'token': token })) }}
Useful for sending an AJAX response with a large number of objects which can be independently cached
// Controller.php
<?php
public function indexAction()
{
$jsonObjects = array();
foreach ($objects as $object) {
$content = $this->get('templating.helper.actions')
->render('viewObjectAsJson',
array('id' => $object->getId())
array('standalone' => true));
$jsonObjects[] = $this->get('jamesi_http_cache.helper')
->processJsonContent($content);
}
$responseContent = array(
'foo' => 'bar',
'objects' => $jsonObjects,
);
$response = new Response();
$response->setContent(json_encode($responseContent));
return $response;
}