Symfony2:切换区域设置期间的向后 Uri(Referrer)

2022-01-11 00:00:00 referrer localization php symfony

我想实现语言环境切换器,但似乎没有运气......

下面的代码不起作用,因为 (Referrer) 包含 locale 的旧值...

如何使用新的语言环境值重定向到旧的引荐来源网址?

-- 路由.yml

你好:模式:/{_locale}/hello/{name}默认值:{_controller:JetInformBundle:默认:索引,名称:'alexander'}要求:_locale: ^en|de|ru|uk$关于:模式:/{_locale}/about默认值:{ _controller: JetInformBundle:Default:about }要求:_locale: ^en|de|ru|uk$语言环境:模式:/locale/{locale}默认值:{ _controller: JetInformBundle:Locale:index }

-- DefaultController.php

getSession()->set('referrer', $request->getRequestUri());return $this->render('JetInformBundle:Default:index.html.twig',数组('name' => $name));}公共函数 aboutAction(Request $request){$request->getSession()->set('referrer', $request->getRequestUri());return $this->render('JetInformBundle:Default:about.html.twig'));}}

-- LocaleController.php

getSession();if ($request->hasSession())$session->setLocale($locale);return $this->redirect($session->get('referrer'));}}

-- index.html.twig

{% extends '::base.html.twig' %}{% 块体 %}<h1>{% trans %}hello.name{% endtrans %} {{ name }}!</h1><h3>{% trans %}your.locale{% endtrans %} [{{ app.request.get('_locale') }}]</h3>{% 包括 'JetInformBundle:Default:locales.html.twig' %}

<p>{% trans%}return.to{% endtrans%} <a href="{{ path('about', { '_locale': app.request.get('_locale') }) }}">关于</a></p></div>{% 端块 %}-- locales.html.twig<div 类="语言"><ul><li>{% if app.request.get('_locale') == 'ru' %}Русский{% 别的 %}<a href="{{ path('locale', { 'locale': 'ru' }) }}">Русский</a>{% 万一 %}</li><li>{% if app.request.get('_locale') == 'en' %}英语{% 别的 %}<a href="{{ path('locale', { 'locale': 'en' }) }}">英语</a>{% 万一 %}</li><li>{% if app.request.get('_locale') == 'uk' %}Украiнська{% 别的 %}<a href="{{ path('locale', { 'locale': 'uk' }) }}">Украiнська</a>{% 万一 %}</li><li>{% if app.request.get('_locale') == 'de' %}德语{% 别的 %}<a href="{{ path('locale', { 'locale': 'de' }) }}">Deutsch</a>{% 万一 %}</li></ul></div>

解决方案

让我告诉你我的解决方案.我写了内核事件监听器:

<service id="expedio.simple.listener" class="ExpedioSimpleBundleListenerKernel">

如下:

命名空间 ExpedioSimpleBundleListener;使用 SymfonyComponentDependencyInjectionContainerInterface;使用 SymfonyComponentHttpKernelEventGetResponseEvent;类内核{/*** @var SymfonyComponentDependencyInjectionContainerInterface*/私人$路由器;公共函数 __construct(SymfonyComponentRoutingRouter $router) {$this->router = $router;}公共函数 onKernelRequest(GetResponseEvent $event) {if ($event->getRequestType() !== SymfonyComponentHttpKernelHttpKernel::MASTER_REQUEST) {返回;}/** @var SymfonyComponentHttpFoundationRequest $request */$request = $event->getRequest();/** @var SymfonyComponentHttpFoundationSession $session */$session = $request->getSession();$routeParams = $this->router->match($request->getPathInfo());$routeName = $routeParams['_route'];if ($routeName[0] == '_') {返回;}未设置($routeParams['_route']);$routeData = array('name' => $routeName, 'params' => $routeParams);//跳过重复项$thisRoute = $session->get('this_route', array());if ($thisRoute == $routeData) {返回;}$session->set('last_route', $thisRoute);$session->set('this_route', $routeData);}}

它只是在用户每次打开页面时保存最后一次请求路由数据.在控制器中,当用户想要更改语言环境时,我会这样做:

/*** @Route("/setlocale/{locale}", name="set_locale")* @param 字符串 $locale* @return 数组*/公共函数 setLocaleAction($locale) {/** @var SymfonyComponentHttpFoundationSession $session */$session = $this->get('session');$session->setLocale($locale);$last_route = $session->get('last_route', array('name' => 'index'));$last_route['params']['_locale'] = $locale;return ($this->redirect($this->generateUrl($last_route['name'], $last_route['params'])));}

I'd like to implement locale switcher, but it seems with no luck...

The code below doesn't work because the (Referrer) contains the old value of locale...

How can I redirect to the old Referrer URI with a new value of locale?

-- routing.yml

hello:
  pattern:  /{_locale}/hello/{name}
  defaults: { _controller: JetInformBundle:Default:index, name: 'alexander' }
  requirements:
    _locale: ^en|de|ru|uk$

about:
  pattern:  /{_locale}/about
  defaults: { _controller: JetInformBundle:Default:about }
  requirements:
    _locale: ^en|de|ru|uk$

locale:
  pattern:  /locale/{locale}
  defaults: { _controller: JetInformBundle:Locale:index }

-- DefaultController.php

<?php

namespace JetInformBundleController;

use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SensioBundleFrameworkExtraBundleConfigurationTemplate;
use SymfonyComponentHttpFoundationRequest;

class DefaultController extends Controller
{
    public function indexAction($name, Request $request)
    {
        $request->getSession()->set('referrer', $request->getRequestUri());
        return $this->render('JetInformBundle:Default:index.html.twig',
                             array('name' => $name));
    }

    public function aboutAction(Request $request)
    {
        $request->getSession()->set('referrer', $request->getRequestUri());
        return $this->render('JetInformBundle:Default:about.html.twig'));
    }
}

-- LocaleController.php

<?php

namespace JetInformBundleController;

use SymfonyBundleFrameworkBundleControllerController;
use SensioBundleFrameworkExtraBundleConfigurationRoute;
use SensioBundleFrameworkExtraBundleConfigurationTemplate;
use SymfonyComponentHttpFoundationRequest;

class LocaleController extends Controller
{
    public function indexAction($locale, Request $request)
    {
        $session = $request->getSession();

        if ($request->hasSession())
            $session->setLocale($locale);

        return $this->redirect($session->get('referrer'));
    }
}

-- index.html.twig

{% extends '::base.html.twig' %}

{% block body %}
<h1>{% trans %}hello.name{% endtrans %} {{ name }}!</h1>
<h3>{% trans %}your.locale{% endtrans %} [{{ app.request.get('_locale') }}]</h3>

{% include 'JetInformBundle:Default:locales.html.twig' %}

<div>
    <p>{% trans%}return.to{% endtrans%} <a href="{{ path('about', { '_locale':   app.request.get('_locale') }) }}">About</a></p>
</div>
{% endblock %}

-- locales.html.twig

<div class="langs">
    <ul>
        <li>
            {% if app.request.get('_locale') == 'ru' %}
                Русский
            {% else %}
                <a href="{{ path('locale', { 'locale': 'ru' }) }}">Русский</a>
            {% endif %}
        </li>
        <li>
            {% if app.request.get('_locale') == 'en' %}
                English
            {% else %}
                <a href="{{ path('locale', { 'locale': 'en' }) }}">English</a>
            {% endif %}
        </li>
        <li>
            {% if app.request.get('_locale') == 'uk' %}
                Украiнська
            {% else %}
                <a href="{{ path('locale', { 'locale': 'uk' }) }}">Украiнська</a>
            {% endif %}
        </li>
        <li>
            {% if app.request.get('_locale') == 'de' %}
                Deutsch
            {% else %}
                <a href="{{ path('locale', { 'locale': 'de' }) }}">Deutsch</a>
            {% endif %}
        </li>
    </ul>
</div>

解决方案

Let me show you my solution. I've written kernel event listener:

<service id="expedio.simple.listener" class="ExpedioSimpleBundleListenerKernel">
      <tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" />
      <argument type="service" id="router" />
  </service>

like the following:

namespace ExpedioSimpleBundleListener;

use SymfonyComponentDependencyInjectionContainerInterface;
use SymfonyComponentHttpKernelEventGetResponseEvent;

class Kernel {

    /**
     * @var SymfonyComponentDependencyInjectionContainerInterface
     */
    private $router;

    public function __construct(SymfonyComponentRoutingRouter $router) {
        $this->router = $router;
    }

    public function onKernelRequest(GetResponseEvent $event) {
        if ($event->getRequestType() !== SymfonyComponentHttpKernelHttpKernel::MASTER_REQUEST) {
            return;
        }

        /** @var SymfonyComponentHttpFoundationRequest $request  */
        $request = $event->getRequest();
        /** @var SymfonyComponentHttpFoundationSession $session  */
        $session = $request->getSession();

        $routeParams = $this->router->match($request->getPathInfo());
        $routeName = $routeParams['_route'];
        if ($routeName[0] == '_') {
            return;
        }
        unset($routeParams['_route']);
        $routeData = array('name' => $routeName, 'params' => $routeParams);

        //Skipping duplicates
        $thisRoute = $session->get('this_route', array());
        if ($thisRoute == $routeData) {
            return;
        }
        $session->set('last_route', $thisRoute);
        $session->set('this_route', $routeData);
    }
}

It just saves last request route data each time user opens a page. And in controller when user wants to change locale I do this:

/**
 * @Route("/setlocale/{locale}", name="set_locale")
 * @param string $locale
 * @return array
 */
public function setLocaleAction($locale) {
    /** @var SymfonyComponentHttpFoundationSession $session  */
    $session = $this->get('session');
    $session->setLocale($locale);
    $last_route = $session->get('last_route', array('name' => 'index'));
    $last_route['params']['_locale'] = $locale;
    return ($this->redirect($this->generateUrl($last_route['name'], $last_route['params'])));
}

相关文章