问题
In order to set the response without the cache in the controller you can do this:
$response = new Response();
$result = $this->renderView(
'AcmeDemoBundle:Default:index.html.twig',
array('products' => $products, 'form' => $form->createView()));
$response->headers->addCacheControlDirective('no-cache', true);
$response->headers->addCacheControlDirective('max-age', 0);
$response->headers->addCacheControlDirective('must-revalidate', true);
$response->headers->addCacheControlDirective('no-store', true);
$response->setContent($result);
return $response;
But using annotations, to ensure that each method has the same result, how can you do?
I tried so but continues to save the cache and if I use the browser's Back button keeps the cache:
/**
* @Cache(maxage="0", vary="no-cache, must-revalidate, no-store", smaxage="0", expires="now", public="false")
*/
class DefaultController extends Controller
{
/**
* Homepage: show products
*
* @Route("/", name="homepage")
* @Template
*/
public function indexAction()
{
$sessionCart = $this->get('demo');
$filters = $sessionCart->getFilters($this->getDoctrine()->getEntityManager());
$products = $this->getDoctrine()->getRepository('AcmeDemoBundle:Product')->search($filters);
$form = $this->createForm(new FilterType, $filters);
return array('products' => $products, 'form' => $form->createView());
}
If imposed as the documentation says:
@Cache(vary=["no-cache", "must-revalidate", "no-store"]...
gives me a syntax error which does not expect "[", so I tried as above.
回答1:
You are mixing two things. In your first snippet you are setting cache control headers, but with the annotation you want to set the Vary header. But Vary is complete different than the Cache-Control header, in which no-cache, must-revalidate, no-store should stand. Vary means on which thinks of the request (i.e. Cookies) the Response can vary. See this answer for understanding: https://stackoverflow.com/a/1975677/2084176
In your case (no-cache) you can rely on the defaults, which symfony sets, if no cache headers are present:
Symfony2 automatically sets a sensible and conservative Cache-Control header when none is set by the developer by following these rules:
- If no cache header is defined (
Cache-Control,Expires,ETagorLast-Modified),Cache-Controlis set tono-cache, meaning that the response will not be cached;
EDIT: if you need to set the cache header for every controller action, you can work with the kernel.response event. Create a listener which reacts on this event and modify the response with appropriate cache control.
namespace Acme\DemoBundle\EventListener;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
class AcmeCacheListener
{
public function onKernelResponse(FilterResponseEvent $event)
{
$response = $event->getResponse();
$response->headers->addCacheControlDirective('no-cache', true);
$response->headers->addCacheControlDirective('max-age', 0);
$response->headers->addCacheControlDirective('must-revalidate', true);
$response->headers->addCacheControlDirective('no-store', true);
}
}
and in your services.yml
services:
kernel.listener.your_listener_name:
class: Acme\DemoBundle\EventListener\AcmeCacheListener
tags:
- { name: kernel.event_listener, event: kernel.response, method: onKernelResponse }
回答2:
I guess that the main problem it's that Cache annotation doesn't have an option for no-cache, no-store and must-revalidate. I can't explain why. As an addition to Patrick's answer, if you have more than one controller and you want to apply the headers to only one, you can check the controller class inside the listener like:
class AcmeCacheListener
{
public function onKernelResponse(FilterResponseEvent $event)
{
$controller = $event->getRequest()->attributes->get('_controller');
$requiredController = "Acme\Controller\DefaultController";
if( substr($controller, 0,strlen($requiredController)) == $requiredController) {
$response = $event->getResponse();
$response->headers->addCacheControlDirective('no-cache', true);
$response->headers->addCacheControlDirective('max-age', 0);
$response->headers->addCacheControlDirective('must-revalidate', true);
$response->headers->addCacheControlDirective('no-store', true);
}
}
}
来源:https://stackoverflow.com/questions/17732454/no-cache-header-with-annotation