3

私はキャッシング用にセットアップしようとしている e コマース アプリケーションを持っています。Apache2 で Symfony 2.1.8 を使用しています。

私の問題は、プライマリ コントローラー アクションがキャッシュされている場合 (バスケット コンテンツのようなプライベート コンテンツにとって重要)、要求ごとに ESI タグを再チェックできないことですが、その理由がわかりません。

たとえば、次のコードでホームページをキャッシュします。

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
        );
    }
}

レンダリングされたテンプレートは、次の ESI を含むベース レイアウト テンプレートを拡張してバスケットを表示します。

{% render 'PurchaseBundle:Basket:summary' with {}, { 'standalone': true } %}

(編集:ディエゴの答えを読んだ後、推奨される構文も使用しました:

{% render url('basket_summary') with {}, {'standalone': true} %}

残念ながら、これは何の違いもありませんでした。)

バスケット サマリーのコードをかなりいじりましたが、これが現在持っているものです。

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
        );
    }
}

ホームページ以外のページ (まだキャッシュされていない) では、バスケット サマリーのキャッシュは正常に機能し、常に正しいデータが表示されます。古い情報が表示されるのは、ホームページに戻ったときだけです。ログは、実際にレンダリングしsummaryActionない限り、ホームページで呼び出されないことを確認します。indexAction

編集

error_log($kernel->getLog())各ページ要求の後に使用すると、キャッシュされていないページに対して次のようになります。

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

そして、これはキャッシュされたホームページの場合:

GET /: fresh

明らかな何かが欠けているに違いありませんが、ドキュメントはこれをカバーしていないように見えますが、ESI が使用されることになっているようなものであることを暗示しています。

4

2 に答える 2

3

2.0.20/2.1.5 以降、Symfony2 はCVE-2012-6431に従って、コントローラーの論理パスではなく完全修飾 URL を取ります。したがって、現在の ESI の代わりに:

{% render 'PurchaseBundle:Basket:summary' with {}, { 'standalone': true } %}

ルートを作成してから、twig で url メソッドを使用する必要があります。

{% render url('basket_summary') with {}, {'standalone': true} %}

また、本日 (3 月 1 日)、サブリクエスト管理が大幅に改善された Symfony の新しい安定バージョン (2.2.0) がリリースされたことにも注意してください。この新しいバージョンでは、2 つのアプローチを取ることができます ( The Book の HTTP キャッシュの章のマスター バージョンから抽出)。

{# you can use a controller reference #}
{{ render_esi(controller('...:news', { 'max': 5 })) }}

{# ... or a URL #}
{{ render_esi(url('latest_news', { 'max': 5 })) }}

リンクされた章の現在のバージョンのサイド ノートも読む価値があります。実際の問題を見つけるのに役立つ有益な情報とヒントが含まれているからです。

于 2013-03-01T17:31:09.850 に答える