Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/246.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php symfony 2根据数据库中存储的用户首选项设置语言环境_Php_Symfony_Locale - Fatal编程技术网

Php symfony 2根据数据库中存储的用户首选项设置语言环境

Php symfony 2根据数据库中存储的用户首选项设置语言环境,php,symfony,locale,Php,Symfony,Locale,我试图根据数据库中存储的当前用户的首选项设置语言环境 因此,我们的用户类有一个getPreferredLanguage,它返回一个区域设置标识(“en”、“fr\u fr”等) 我考虑了以下方法: 注册订阅KerneleEvents::REQUEST事件的“locale”侦听器服务 此服务可以访问安全上下文(通过其构造函数) 此服务的onKernelRequest方法尝试从安全上下文获取用户,获取用户的首选区域设置,并将其设置为请求的区域设置 不幸的是,这不起作用。调用“locale”侦听器

我试图根据数据库中存储的当前用户的首选项设置语言环境

因此,我们的用户类有一个getPreferredLanguage,它返回一个区域设置标识(“en”、“fr\u fr”等)

我考虑了以下方法:

  • 注册订阅KerneleEvents::REQUEST事件的“locale”侦听器服务
  • 此服务可以访问安全上下文(通过其构造函数)
  • 此服务的onKernelRequest方法尝试从安全上下文获取用户,获取用户的首选区域设置,并将其设置为请求的区域设置
不幸的是,这不起作用。调用“locale”侦听器服务的onRequestEvent方法时,安全上下文没有令牌。上下文侦听器似乎是在非常晚的阶段调用的(优先级为0),并且不可能告诉我的“locale”侦听器在安全上下文之前运行


是否有人知道如何修复此方法,或建议另一种方法?

您可能对locale listener感兴趣,我在下面的回答中发布了此方法:

编辑:如果用户在配置文件中更改其语言,则没有问题。如果您使用的是FOSUserBundle(master),则可以连接到概要文件编辑成功事件。如果您使用自制系统,则在您的配置文件控制器中。以下是FOSUserBundle的一个示例:

<?php
namespace Acme\UserBundle\EventListener;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\FOSUserEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class ChangeLanguageListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(
                FOSUserEvents::PROFILE_EDIT_SUCCESS => 'onProfileEditSuccess',
        );
    }

    public function onProfileEditSuccess(FormEvent $event)
    {
        $request = $event->getRequest();
        $session = $request->getSession();
        $form = $event->getForm();
        $user = $form->getData();
        $lang = $user->getLanguage();

        $session->set('_locale', $lang);
        $request->setLocale($lang);
    }
}
对于多个浏览器中的多个会话没有问题,因为每个新会话都需要新的登录。嗯,好的,在更改语言之后就不会了,因为只有当前会话才会被更新。但您可以修改LanguageListener以支持此功能。

如果管理员更改了语言,这种情况应该无关紧要。

如果你通过谷歌找到这个答案,我目前正在使用这个解决方案

    <?php

namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface;

class SetLocaleEventSubscriber implements EventSubscriberInterface
{

    private Security $security;
    private TranslatorInterface $translator;

    public function __construct(Security $security, TranslatorInterface $translator)
    {
        $this->security = $security;
        $this->translator = $translator;
    }

    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::CONTROLLER => [
                ['setLocale', 1]
            ]
        ];
    }

    public function setLocale(ControllerEvent $event)
    {
        if (!$event->isMasterRequest()) {
            return;
        }
        $request = $event->getRequest();
        /**
         * @var \App\Entit\User
         */
        $user = $this->security->getUser();

        if ($user) {;
            $request->setLocale($user->getLocale());
            $this->translator->setLocale($user->getLocale());
        }
    }
}

我很感激你的回答,这在一定程度上是有帮助的。我早就考虑过这种方法,但有几个用例需要更进一步的逻辑才能得到支持,例如:用户在登录时更改首选语言(需要更新会话)、多个会话(例如,用户通过多个浏览器登录),以及用户首选语言在DB中直接更改(例如,通过管理页面)。这让我想知道是否没有一个更直接的答案来解决这个问题。是的,这会起作用,这当然是一个比我提出的更好的解决方案,但它确实涉及到很多活动部件。由于我的应用程序环境简单,我会选择我公认的次优解决方案(因为我只处理一个防火墙,所以我可以简单地将它的id注入我的侦听器,并使用它从会话中检索安全令牌)。非常感谢。对于我自己的问题,我找到了一个不完美的答案,这是值得的:在内核事件侦听器中,我可以从会话中获取安全令牌并取消序列化,从而获得用户。不幸的是,这依赖于知道防火墙的“contextKey”,这几乎是硬编码的。例如,如果防火墙是“main”,则可以通过:$token=$session->get(“\u security\u main”)从会话中获取令牌;此逻辑是从ContextListener中提取的。但是在配置过程中,context listener通过了防火墙id。您是否尝试过注入安全上下文?然后您可以从上下文中简单地获取令牌和用户。Pazi,注入安全上下文不起作用。这是此票据的全部要点。我没有正是他的问题,找到好的解决办法了吗?
    <?php

namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface;

class SetLocaleEventSubscriber implements EventSubscriberInterface
{

    private Security $security;
    private TranslatorInterface $translator;

    public function __construct(Security $security, TranslatorInterface $translator)
    {
        $this->security = $security;
        $this->translator = $translator;
    }

    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::CONTROLLER => [
                ['setLocale', 1]
            ]
        ];
    }

    public function setLocale(ControllerEvent $event)
    {
        if (!$event->isMasterRequest()) {
            return;
        }
        $request = $event->getRequest();
        /**
         * @var \App\Entit\User
         */
        $user = $this->security->getUser();

        if ($user) {;
            $request->setLocale($user->getLocale());
            $this->translator->setLocale($user->getLocale());
        }
    }
}