I have an ecommerce application that I'm try to set up for caching - initially via the Symfony2 Reverse Proxy, but then ultimately via Varnish in production. I'm using Symfony 2.1.8 on Apache2.
My problem is I cannot get the ESI tags to be re-checked for each request when the primary controller action is cached (important for private content like the basket contents), but I don't understand why.
For example, I cache the homepage with the following code:
public function indexAction(Request $request)
{
// check cache
$homepage = $this->getHomepage();
$response = new Response();
$response->setPublic();
$etag = md5('homepage'.$homepage->getUpdated()->getTimestamp());
$response->setETag($etag);
$response->setLastModified($homepage->getUpdated());
if ($response->isNotModified($request))
{
// use cached version
return $response;
}
else
{
return $this->render(
'StoreBundle:Store:index.html.twig',
array(
'page' => $homepage
),
$response
);
}
}
The rendered template extends the base layout template which includes the following ESI to show the basket:
{% render 'PurchaseBundle:Basket:summary' with {}, { 'standalone': true } %}
(Edit: After reading Diego's answer, I have also used the recommended syntax:
{% render url('basket_summary') with {}, {'standalone': true} %}
Unfortunately this had not made any difference.)
I've been playing with the code for the basket summary quite a bit, but this is what I have at present.
public function summaryAction()
{
$response = new Response();
$response->setPrivate();
$response->setVary(array('Accept-Encoding', 'Cookie'));
if ($this->basket->getId())
{
$etag = md5($this->getUniqueEtag());
$response->setLastModified($this->basket->getUpdated());
}
else
{
$etag = md5('basket_summary_empty');
}
$response->setETag($etag);
if ($response->isNotModified($this->request))
{
// use cached version
return $response;
}
else
{
return $this->render(
'PurchaseBundle:Basket:summary.html.twig',
array(
'basket' => $this->basket
),
$response
);
}
}
On pages other than the homepage (which are not cached yet) the basket summary caching works just fine, it always displays the correct data. It's only when you return to the homepage that you'd see outdated information. Logging confirms that summaryAction
is not called on the homepage unless indexAction
actually renders.
Edit
Using error_log($kernel->getLog())
after each page request I get this for a non-cached page:
GET /categories/collections: miss; GET /_internal/secure/PurchaseBundle:Basket:summary/none.html: stale, valid, store; GET /_internal/secure/CatalogBundle:Search:form/none.html: miss; GET /esi/menu/main: fresh
And this for the cached homepage:
GET /: fresh
I must be missing something obvious, but the documentation doesn't appear to cover this, yet it implies it's just the sort of thing ESI is supposed to be used for.