解释Symfony的“粘性”区域设置事件侦听器


Explain Symfony's "sticky" locale event listener

Symfony的食谱提出了以下方法,以使语言环境在用户会话期间"粘性":

class LocaleListener implements EventSubscriberInterface
{
    private $defaultLocale;
    public function __construct($defaultLocale = 'en')
    {
        $this->defaultLocale = $defaultLocale;
    }
    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        if (!$request->hasPreviousSession()) {
            return;
        }
        // try to see if the locale has been set as a _locale routing parameter
        if ($locale = $request->attributes->get('_locale')) {
            $request->getSession()->set('_locale', $locale);
        } else {
            // if no explicit locale has been set on this request, use one from the session
            $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
        }
    }
    public static function getSubscribedEvents()
    {
        return array(
            // must be registered before the default Locale listener
            KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
        );
    }
}

谁能解释以下三点:

  1. 如果! $request->hasPreviousSession(),他们为什么return
  2. int 以下if/else,为什么他们在if块中设置带有 $request->getSession()->set('_locale') 的区域设置?为什么不使用else块中的$request->setLocale()
  3. "必须在默认区域设置侦听器之前注册"到底是什么意思?

此事件将使_locale看起来像是与当前请求一起提交的,即使它实际上可能来自会话(但_locale可能在请求中 - 例如,当用户更改区域设置时 - 在这种情况下将会话对象更新为新值)。

回答您的问题。

  1. 如果没有会话对象,则跳过,因为事件是多余的(值不能在会话中,因为它不存在)。

  2. 在会话和请求之间同步 _locale 的值,以支持请求的版本。

  3. 由于 LocaleListener 事件处理区域设置问题,因此需要在事件运行之前发生上述操作。OnKernelRequest 是第一个被触发的事件之一,因此我们可以确定情况确实如此。