带有Symfony内置反向代理的FOSHttpCacheBundle缓存无效不';行不通

带有Symfony内置反向代理的FOSHttpCacheBundle缓存无效不';行不通,symfony,caching,cache-invalidation,foshttpcachebundle,Symfony,Caching,Cache Invalidation,Foshttpcachebundle,我正在尝试做一件困难的事情:使用FOSHttpCacheBundle 2.9.0和内置的Symfony反向代理在Symfony 4.4.13中实现缓存失效。 不幸的是,我不能使用其他缓存解决方案(如Varnish或Nginx),因为我的托管服务不提供它们。因此,Symfony内置的反向代理是我唯一的解决方案 我已经安装并配置了FOSHttpCacheBundle(遵循)。还创建了一个CacheKernel类,并修改了内核以使用它(如下和) 经过几次测试(使用我的浏览器),HTTP缓存工作并缓存G

我正在尝试做一件困难的事情:使用FOSHttpCacheBundle 2.9.0和内置的Symfony反向代理在Symfony 4.4.13中实现缓存失效。 不幸的是,我不能使用其他缓存解决方案(如Varnish或Nginx),因为我的托管服务不提供它们。因此,Symfony内置的反向代理是我唯一的解决方案

我已经安装并配置了FOSHttpCacheBundle(遵循)。还创建了一个CacheKernel类,并修改了内核以使用它(如下和)

经过几次测试(使用我的浏览器),HTTP缓存工作并缓存GET响应(见浏览器网络分析器)。但是,当我使用PUT/PATCH/POST更新资源时,GET响应仍然来自缓存,并且在过期之前保持不变。我的推论是无效宣告无效

我做错什么了吗?你能帮我排除故障吗? 请参阅下面我的代码和配置

config/packages/fos_http_cache.yaml

fos_http_cache:
    cache_control:
        rules:
            -
                match:
                    path: ^/
                headers:
                    cache_control:
                        public: true
                        max_age: 15
                        s_maxage: 30
                    etag: "strong"
    cache_manager:
        enabled: true
    invalidation:
        enabled: true
    proxy_client:
        symfony:
            tags_header: My-Cache-Tags
            tags_method: TAGPURGE
            header_length: 1234
            purge_method: PURGE
            use_kernel_dispatcher: true
src/CacheKernel.php

<?php
namespace App;

use FOS\HttpCache\SymfonyCache\CacheInvalidation;
use FOS\HttpCache\SymfonyCache\CustomTtlListener;
use FOS\HttpCache\SymfonyCache\DebugListener;
use FOS\HttpCache\SymfonyCache\EventDispatchingHttpCache;
use FOS\HttpCache\SymfonyCache\PurgeListener;
use FOS\HttpCache\SymfonyCache\RefreshListener;
use FOS\HttpCache\SymfonyCache\UserContextListener;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpCache\HttpCache;
use Symfony\Component\HttpKernel\HttpCache\Store;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class CacheKernel extends HttpCache implements CacheInvalidation
{
    use EventDispatchingHttpCache;

    // Overwrite constructor to register event listeners for FOSHttpCache.
    public function __construct(HttpKernelInterface $kernel, SurrogateInterface $surrogate = null, array $options = [])
    {
        parent::__construct($kernel, new Store($kernel->getCacheDir()), $surrogate, $options);

        $this->addSubscriber(new CustomTtlListener());
        $this->addSubscriber(new PurgeListener());
        $this->addSubscriber(new RefreshListener());
        $this->addSubscriber(new UserContextListener());
        if (isset($options['debug']) && $options['debug'])
            $this->addSubscriber(new DebugListener());
    }

    // Made public to allow event listeners to do refresh operations.
    public function fetch(Request $request, $catch = false)
    {
        return parent::fetch($request, $catch);
    }
}
<?php
namespace App;

use FOS\HttpCache\SymfonyCache\HttpCacheAware;
use FOS\HttpCache\SymfonyCache\HttpCacheProvider;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
use Symfony\Component\Routing\RouteCollectionBuilder;

class Kernel extends BaseKernel implements HttpCacheProvider
{
    use MicroKernelTrait;
    use HttpCacheAware;

    private const CONFIG_EXTS = '.{php,xml,yaml,yml}';

    public function __construct(string $environment, bool $debug)
    {
        parent::__construct($environment, $debug);
        $this->setHttpCache(new CacheKernel($this));
    }
...
setHttpCache(新的CacheKernel($this));
}
...
public/index.php

<?php
use App\Kernel;
use Symfony\Component\ErrorHandler\Debug;
use Symfony\Component\HttpFoundation\Request;

require dirname(__DIR__).'/config/bootstrap.php';

...

$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
$kernel = $kernel->getHttpCache();
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

经过几天的搜索,我自己找到了解决方案

CacheKernel
中,我扩展了FOSHttpCache文档中描述的
Symfony\Component\HttpKernel\HttpCache\HttpCache
。但是,该类必须扩展
Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache
,如Symfony文档中所述。结果,构造函数也发生了变化

老实说,我不知道这两个类之间的区别,但是如果您想要有一个内置的函数式反向代理,就必须使用第二个类。现在对我有效了

我把src/CacheKernel.php的最终代码放在这里:

<?php

namespace App;

use FOS\HttpCache\SymfonyCache\CacheInvalidation;
use FOS\HttpCache\SymfonyCache\CustomTtlListener;
use FOS\HttpCache\SymfonyCache\DebugListener;
use FOS\HttpCache\SymfonyCache\EventDispatchingHttpCache;
use FOS\HttpCache\SymfonyCache\PurgeListener;
use FOS\HttpCache\SymfonyCache\RefreshListener;
use FOS\HttpCache\SymfonyCache\UserContextListener;
use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class CacheKernel extends HttpCache implements CacheInvalidation
{
    use EventDispatchingHttpCache;

    /**
     * Overwrite constructor to register event listeners for FOSHttpCache.
     */
    public function __construct(HttpKernelInterface $kernel)
    {
        parent::__construct($kernel, $kernel->getCacheDir());

        $this->addSubscriber(new CustomTtlListener());
        $this->addSubscriber(new PurgeListener());
        $this->addSubscriber(new RefreshListener());
        $this->addSubscriber(new UserContextListener());
        if (isset($options['debug']) && $options['debug'])
            $this->addSubscriber(new DebugListener());
    }

    /**
     * Made public to allow event listeners to do refresh operations.
     *
     * {@inheritDoc}
     */
    public function fetch(Request $request, $catch = false)
    {
        return parent::fetch($request, $catch);
    }
}

成功了,谢谢你的回答
<?php

namespace App;

use FOS\HttpCache\SymfonyCache\CacheInvalidation;
use FOS\HttpCache\SymfonyCache\CustomTtlListener;
use FOS\HttpCache\SymfonyCache\DebugListener;
use FOS\HttpCache\SymfonyCache\EventDispatchingHttpCache;
use FOS\HttpCache\SymfonyCache\PurgeListener;
use FOS\HttpCache\SymfonyCache\RefreshListener;
use FOS\HttpCache\SymfonyCache\UserContextListener;
use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class CacheKernel extends HttpCache implements CacheInvalidation
{
    use EventDispatchingHttpCache;

    /**
     * Overwrite constructor to register event listeners for FOSHttpCache.
     */
    public function __construct(HttpKernelInterface $kernel)
    {
        parent::__construct($kernel, $kernel->getCacheDir());

        $this->addSubscriber(new CustomTtlListener());
        $this->addSubscriber(new PurgeListener());
        $this->addSubscriber(new RefreshListener());
        $this->addSubscriber(new UserContextListener());
        if (isset($options['debug']) && $options['debug'])
            $this->addSubscriber(new DebugListener());
    }

    /**
     * Made public to allow event listeners to do refresh operations.
     *
     * {@inheritDoc}
     */
    public function fetch(Request $request, $catch = false)
    {
        return parent::fetch($request, $catch);
    }
}