Php Symfony 3中的ESI缓存

Php Symfony 3中的ESI缓存,php,caching,symfony,http-caching,esi,Php,Caching,Symfony,Http Caching,Esi,我已经在我的Symfony 3应用程序中启用了ESI,我在app\u dev.php中也启用了ESI: $kernel = new AppKernel('dev', true); $kernel = new AppCache($kernel); 现在我有了config.yml: framework: esi: { enabled: true } fragments: { path: /_fragment } 在我的控制器中: /** * @Route("/foo/bar/{

我已经在我的Symfony 3应用程序中启用了ESI,我在
app\u dev.php
中也启用了ESI:

$kernel = new AppKernel('dev', true);
$kernel = new AppCache($kernel);
现在我有了
config.yml

framework:
    esi: { enabled: true }
    fragments: { path: /_fragment }
在我的控制器中:

/**
 * @Route("/foo/bar/{fooId}", name="AppBundle_Foo_bar")
 */
public function barAction(int $fooId, Request $request)
{
    //some database querying from repositroy
    $response = $this->render('AppBundle:Foo:bar.html.twig',['foo' => $foo]);
    $response->setETag(md5($response->getContent()));
    $response->setPublic();
    $response->isNotModified($request);

    return $response;
}
这是我要缓存的视图(
bar.html.twig
),看起来像:

{{foo}}
{% extends 'AppBundle::layout.html.twig' %}
{% block content %}
    {{ render_esi(controller('AppBundle:Foo:bar', { 'fooId': fooId })) }}
{% endblock content %}
现在,我有另一个方法来渲染主视图

/**
 * @Route("/baz/{fooId}", name="AppBundle_Foo_baz")
 * @Template
 */
public function bazAction(int $fooId)
{
    return [
        'fooId' => $fooId
    ];
}
我的
baz.html.twig
看起来像:

{{foo}}
{% extends 'AppBundle::layout.html.twig' %}
{% block content %}
    {{ render_esi(controller('AppBundle:Foo:bar', { 'fooId': fooId })) }}
{% endblock content %}
因此,我希望主要使用非缓存视图(baz)和嵌套
barAction()
,并将其缓存

但是,我得到了:

Cache-Control:must-revalidate, no-cache, private 
即使我将其显式设置为public,我也得到:

X-Symfony-Cache:GET /baz/1: miss; 
每次刷新页面时,我都会得到:

GET /_fragment?_hash=aO.....Details: stale, invalid, store 
如果我刷新,无效变为有效。但我不能设置缓存

编辑:

我读过关于ESI和验证缓存的文章,但它们似乎不能一起工作。所以我尝试了验证缓存并添加了

$response->setSharedMaxAge(15);
$response->headers->addCacheControlDirective('must-revalidate', true);

而不是ETag。同样的结果…

我遵循了您的代码/设置,但我添加了一个时间戳以打印在
bar.html.twig
中。它肯定会缓存ESI块。您提到的响应头是主请求上的响应头还是ESI块上的响应头?即使缓存公共块,主请求仍然可以是私有的。尝试向模板添加一个时间戳,看看它是否被缓存或更改。嗯,我认为当在其他头中调用一个控制器时,其他头将被合并。我将尝试添加时间戳以检查缓存。我也会在主请求中添加登录按钮。所以当我通过chrome登录时,它会打印我的用户名而不是登录按钮,当我在firefox中打开页面时,我会看到登录按钮而不是chrome会话中的用户名。我会报告结果。试着在Symfony之外思考。ESI可以由许多反向代理(例如:Varnish)支持。在您的例子中,它是AppCache类。当您得到一个反向代理来构造发送到客户端的页面时会发生什么:1。代理加载第2页。ESI检查包括标签3。if tag found对该块发出另一个HTTP请求(如果public或vary头允许,则从缓存提供服务)4。将构造好的HTML发送到客户端注意:要小心缓存的块,它不应该包含私有信息(除非使用vary,但那是另一回事)!是的,你说得对。今天晚些时候,我将尝试从我的示例构建ESI并报告结果。