Symfony3登录后保持语言环境

时间:2017-01-16 15:27:46

标签: php symfony symfony-3.1

我遇到的问题是,当用户在登录页面中更改语言时 - 它可以正常工作,但在用户登录后 - 它又重新恢复为默认状态。如何在登录前保持同一语言用户的选择,登录后留下来? 我已尝试在stackoverflow上查找,但无法找到任何正常工作结果。

security.yml:

security:

    encoders:
        AppBundle\Entity\User:
            algorithm: bcrypt

    role_hierarchy:
        ROLE_ADMIN: ROLE_PREMIUM
        ROLE_PREMIUM: ROLE_USER

    providers:
        our_db_provider:
            entity:
                class: AppBundle:User
                property: email

        in_memory:
            memory: ~

    firewalls:
        # disables authentication for assets and the profiler, adapt it according to your needs
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

        main:
            anonymous: ~

            form_login:
                #galima nurodyti kur nukreipia loginas
                login_path: login
                check_path: login
                csrf_token_generator: security.csrf.token_manager 
            logout:
                path:   /logout

            pattern:    ^/
            http_basic: ~
            provider: our_db_provider
            access_denied_url: homepage

的routing.yml

app:
    resource: "@AppBundle/Controller/"
    type:     annotation
    prefix:   /{_locale}
    requirements:
        _locale: lt|en|ru

root:
    path: /
    defaults:
        _controller: FrameworkBundle:Redirect:urlRedirect
        path: /%locale%/
        permanent: true  

login:
    path:  /{_locale}/login
    defaults: { _controller: AppBundle:Security:login }
    requirements:
        _method:  GET
        _locale: lt|en|ru

logout:
    path: /logout
    defaults:
        _controller: FrameworkBundle:Redirect:urlRedirect
        path: /{_locale}/login
        permanent: true        

register:
    path:  /{_locale}/register
    defaults: { _controller: AppBundle:Registration:register }
    requirements:
        _method:  GET
        _locale: lt|en|ru                

语言改变了:

<ul class="top-menu-list top-menu-languages">
    <li><a href="{{ path(app.request.attributes.get('_route'), app.request.query.all|merge({'_locale': 'lt'})) }}">LT</a></li>
    <li><a href="{{ path(app.request.attributes.get('_route'), app.request.query.all|merge({'_locale': 'en'})) }}">EN</a></li>
    <li><a href="{{ path(app.request.attributes.get('_route'), app.request.query.all|merge({'_locale': 'ru'})) }}">RU</a></li>
</ul>

任何想法或例子都将不胜感激!

1 个答案:

答案 0 :(得分:2)

默认情况下,安全组件会将最后一个请求URI(例如/en/admin)的信息保留在名为_security.main.target_path的会话变量中(其中main是防火墙的名称,已定义在security.yml)。成功登录后,用户将被重定向到此路径,以帮助他们从他们访问过的最后一个已知页面继续。

  

注意:无论登录页面上的语言更改次数多少,因为防火墙在成功登录后始终会重定向到/en/admin/,因此区域设置会再次更改为en

要解决此问题,您可能需要https://community.cloudera.com/t5/Batch-Processing-and-Workflow/Oozie-launcher-never-ends/td-p/13330

异常侦听器类:

// src/AppBundle/Security/Firewall/ExceptionListener.php

use Symfony\Component\Security\Http\Firewall\ExceptionListener as BaseExceptionListener;

class ExceptionListener extends BaseExceptionListener
{
    use TargetPathTrait;

    protected function setTargetPath(Request $request)
    {
        if ($request->hasSession() && $request->isMethodSafe(false) && !$request->isXmlHttpRequest()) {
            $this->saveTargetPath(
                $request->getSession(), 
                // the firewall name 
                'admin', 
                // save the route name instead of the URI
                $request->attributes->get('_route') 
            );
        }
    }
}

使用当前语言环境登录后生成旧路由。

<强>配置:

对于Symfony 2:

# app/config/services.yml
parameters:
    # ...
    security.exception_listener.class: AppBundle\Security\Firewall\ExceptionListener

对于Symfony 3:

您可能需要创建编译器传递并手动更改此类:

// src/AppBundle/DependencyInjection/Compiler/ExceptionListenerPass.php;

class ExceptionListenerPass implements CompilerPassInterface
{
    /**
     * {@inheritdoc}
     */
    public function process(ContainerBuilder $container)
    {
        $definition = $container->getDefinition('security.exception_listener.admin');
        $definition->setClass('AppBundle\Security\Firewall\ExceptionListener');
    }
}

最后在你的包中注册编译器传递:

// src/AppBundle/AppBundle.php

class AppBundle extends Bundle
{   
    public function build(ContainerBuilder $container)
    {
        $container->addCompilerPass(new ExceptionListenerPass());
    }
}