No cache header with annotation

会有一股神秘感。 提交于 2019-11-27 15:15:30

问题


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, ETag or Last-Modified), Cache-Control is set to no-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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!