1

我怎样才能让清漆以不同的状态缓存动态菜单?

我当前的项目(基于 Symfony 2.8)使用KnpMenuBundle和 varnish 来缓存页面。它还ESI用于禁用缓存某些页面上的特定元素。其中包括菜单。但是由于这不是一个变化很大的元素,我想知道是否可以缓存菜单的不同状态并将相关的状态传递给当前调用菜单的页面。

涉及的主要文件如下:

main.html.twig

{{ render_esi(controller('AppBundle:Menu:mainESI')) }}

AppBundle\Controller\MenuController.php

    public function mainESIAction($path = null)
    {
        return $this->render('menu/main_menu_esi.html.twig', [
            'path' => $path
        ]);
    }

菜单/main_menu_esi.html.twig

    {{ knp_menu_render('main-menu', {'template':'menu/main_menu.html.twig'}) }}
4

3 回答 3

2

我对 Symfony 的了解还不够,但总的来说,如果你能够从 cookie 中获取所需的状态,你可以试试这个场景:

在 recv() 中:

  • 解析 Cookie 标头并将您的状态提取到自定义请求 HTTP 标头,比如说“X-Menu-Mode:admin”
  • 删除所有 cookie

在哈希()中:

  • 将该标头添加到哈希中(默认情况下有 URL 和主机 AFAIK)

在未命中/通过 (3.x) 或 backend_fetch (4.x) 中:

  • 从 X-Menu-Mode 重建 bereq 中的 Cookie 标头
  • 从 bereq 中删除 X-Menu-Mode

我已经成功地使用了这个场景。ESI 包含的片段现在可以完全缓存,并为每个唯一的 cookie 值提供不同的版本。

于 2016-08-02T17:21:23.783 回答
1

你不能。

对于 Varnish,url 将是相同的,因此它会呈现相同的。

将您的逻辑应用到外部并将参数添加到您的路线:

{% if is_granted('ROLE_ADMIN') %}
    {% set menu_mode = 'admin' %}
{% else %}
    {% set menu_mode = 'normal' %}
{% endif %}

{{ render_ssi(controller('AppBundle:Menu:mainESI',{'menu_mode':menu_mode}))  }}
于 2016-07-27T15:17:50.067 回答
1

所以这毕竟是可能的。满足我需求的解决方案如下:

  1. 通过树枝传递当前路径:

AppBundle/Resources/views/base.html.twig

{{ render_esi(controller('AppBundle:Menu:mainESI', { 'currentPath': currentPath })) }}
  1. 获取控制器动作中的变量:

AppBundle/Controller/MenuAdminController.php

public function mainESIAction($currentPath = null) 
{
    return $this->render('menu/main_menu_esi.html.twig', [
         'currentPath' => $currentPath,
    ]);
}
  1. 使用 Matcher/Voter 类:

AppBundle/Matcher/Voter/PathVoter.php

<?php

namespace AppBundle\Matcher\Voter;

use Knp\Menu\ItemInterface;
use Knp\Menu\Matcher\Voter\VoterInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Class PathVoter
 */
class PathVoter implements VoterInterface
{
    protected $uri;

    /**
     * @param RequestStack $requestStack
     */
    public function setRequest(RequestStack $requestStack)
    {
        if (($request = $requestStack->getCurrentRequest())) {
            $pathInfo = $request->getPathInfo();
            $requestUri = $request->getRequestUri();

            if (!empty($pathInfo) && '/_fragment' === $pathInfo && !empty($request->attributes->get('currentPath'))) {
                $this->uri = $request->attributes->get('currentPath');
            } else {
                $this->uri = $pathInfo;
            }
        }
    }

    /**
     * @param ItemInterface $item
     * @return bool|void
     */
    public function matchItem(ItemInterface $item)
    {
        $uri = $item->getUri();

        if ((null === $this->uri) || (null === $uri)) {
            return;
        }

        if ($item->getUri() === $this->uri) {
            return true;
        }

        return;
    }
}
  1. 登记选民

AppBundle/Resources/config/services.yml

parameters:
    app.menu.voter.class: AppBundle\MenuBundle\Matcher\Voter\PathVoter

services:
    app.menu.voter:
    class: %app.menu.voter.class%
    calls:
        - [setRequest, [@request_stack]]
    tags:
        - { name: knp_menu.voter }
于 2016-08-05T10:39:40.483 回答