在每个 link 上保留查询字符串

Keep query-string on every link

我想通过让用户在顶部导航的选择框中选择一个城市来个性化我的 Symfony 项目。为此,我得到了一个查询字符串,例如?city=berlin,我在我的控制器中获取并过滤结果。

是否有一种简单的方法可以使每个 url 上的查询字符串保持活动状态,或者您更喜欢没有查询字符串的其他解决方案?也许用饼干?

感谢您的帮助!

如果您需要根据路由路径将用户限制在某些条件下(我建议您使用 SEO 网址而不是 GET 查询),然后将其用作其他页面上某些行为的过滤器,那么您可以这样做听众:

基础内核事件:

namespace App\CoreBundle\Listener;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

abstract class BaseKernelEvents
{
    /**
     * @var \Symfony\Bundle\FrameworkBundle\Routing\Router
     */
    private $router;

    /**
     * Initializes a new instance of the KernelEvents class.
     */
    public function __construct(ContainerInterface $container, Router $router)
    {   
        $this->container = $container;
        $this->router = $router;
    }

    /*
     * Store and get value by route param passed to uri to request and session
     */
    protected function storeParam(GetResponseEvent $event, $name, $default = 'none')
    {
        /* @var $request \Symfony\Component\HttpFoundation\Request */
        $request = $event->getRequest();

        /* @var $session \Symfony\Component\HttpFoundation\Session\Session */
        $session = $request->getSession();

        // instead of attributes you can get query from request here
        $value = $request->attributes->get($name);
        if (!$value) {
            $value = $session->get($name, $default);
        }

        return $this->setValues($event, $name, $value);
    }

    /*
     * Set name/value to request context and session
     */
    protected function setValues(GetResponseEvent $event, $name, $value)
    {
        /* @var $request \Symfony\Component\HttpFoundation\Request */
        $request = $event->getRequest();

        $context = $this->router->getContext();
        $session = $request->getSession();
        $session->set($name, $value);
        $context->setParameter($name, $value);

        return $value;
    }
}

内核事件:

namespace LaMelle\ContentSectionBundle\Listener;

use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

use App\CoreBundle\Listener\BaseKernelEvents;

class KernelEvents extends BaseKernelEvents
{
    public function onKernelRequest(GetResponseEvent $event)
    {
        if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType())
        {
            $contentsectionSlug = $this->storeParam($event, 'city');

            // DO SOMETHINK BASE ON FILTER
            // LIKE CREATE GLOBAL TWIG VAR WITH FILTER VALUE 
            /* @var \Twig_Environment $globals */
            $globals = $this->container->get('twig');
            $globals->addGlobal('city', $contentsectionSlug);

        }
    }
}

因此在所示示例中,您将从会话中填充 'city',直到您访问将 'city' 更改为其他值

的路线

比谈论 cookie 更好的是关于有状态或无状态会话的问题。 Cookies只是将客户端映射到session的实现。

假设您有一位访问者在一个城市参数化页面上。当有人复制 url 并与他人共享时,您除了让您的页面看起来像什么? city 不是任何个人状态,尽管你在上面提到了personalized(例如,具有响应页面,我可以将字体设置为 120% 大小或设置更高相比之下,将是一个个性化的配置我其实不想分享在 url).

city 是页面状态的一部分而不是会话,因此我们希望 city 成为 url 的一部分。定义一个前缀路由,如 /{city} 并导入另一个具有该前缀的 yml (http://symfony.com/doc/current/book/routing.html#prefixing-imported-routes).

每次生成带有城市的 url 时,您都必须对其进行设置。您可以手动执行此操作或创建一些 CityDecoratedRouter implements RouterInterface 以注入 @router@request_stack 并将 city 参数附加到 generate() 中的所有 parameter 数组来电。

@EvgeniyKuzmin 的回答是恕我直言,魔法太多了,没人能想到。在处理那些具有 city 参数的路由时,最好在代码中阅读它,以区别对待路由。当然你还必须为 twig 定义一些新的 city_path 函数,它使用我们的 CityDecoratedRouter.