繁体   English   中英

Symfony 2和遗留应用程序中的自定义会话变量

[英]Symfony 2 and custom session variables from legacy application

我正在设置从Legacy代码库迁移到Symfony代码的能力,我正在尝试在两个应用程序之间共享遗留会话变量。

我现在可以在app_dev.php var_dump($_SESSION) ,并且user_id密钥来自遗留应用程序。 但是,当我在控制器中运行以下内容时,我没有得到任何会话变量:

var_dump($request->getSession()->all());

因此,为了澄清 ,我目前可以访问$_SESSION['user_id'] ,因此会话在应用程序之间成功共享,但Symfony会话对象及其参数包不包含旧密钥。

我的目标:

  • 使user_id键在$request->getSession()调用中可用
  • 这里有所有其他钥匙

我的问题:

我已经尝试过PHP Session桥接,但我认为这不应该按照我想要的那样做。 添加bridge参数不仅不会在我的Symfony应用程序中执行任何操作,而且从我所读到的内容中,这意味着在某个其他遗留应用程序中使用,而不是在Symfony中。

Symfony会话将属性中的数据存储在使用$ _SESSION超全局中的密钥的特殊“包”中。 这意味着Symfony会话无法访问可能由遗留应用程序设置的$ _SESSION中的任意键,尽管保存会话时将保存所有$ _SESSION内容。 [来自与遗留会话的集成 ]

我还看了一下TheodoEvolutionSessionBundle ,但这是旧的,没有得到积极的支持或工作,也不适用于Symfony 3。

我注意到Symfony将它的会话数据存储在$_SESSION['_sf2_attributes'] ,所以我最初的想法是在app_dev.php执行此app_dev.php

$_SESSION['_sf2_attributes']['user_id'] = $_SESSION['user_id'];

显然是错误的方法,因为我也必须在那里调用session_start()

如何将旧的$ _SESSION数据迁移到Symfony的Session对象中? 是否内置了Symfony以帮助提供此功能或捆绑包? 如果没有,我在哪里可以将我的自定义$_SESSION['_sf2_attributes'] 'hack'放在正确的位置来处理所有这些键的迁移?

Symfony在会话中引入了会话包的概念,因此所有内容都是命名空间。 访问非命名空间的会话属性没有构建解决方案。

解决方案是使用标量包,就像TheodoEvolutionSessionBundle一样。 我不会直接使用它,而是实现一些适用于你项目的自定义项目(它们只提供symfony1和codeigniter的集成)。 基于他们的想法,但根据您的需求进行调整。

或者,您可以实现一个kernel.request侦听器,它将遗留的会话属性重写为Symfony:

if (isset($_SESSION['user_id'])) {
    $event->getRequest()->getSession()->set('user_id', $_SESSION['user_id']);
}

吉姆的编辑

我在kernel.request上创建了一个事件监听kernel.request - 每个请求进入,我们遍历$_SESSION所有遗留会话变量并将它们放在Symfony的会话包中。 这是听众:

namespace AppBundle\Session;

use Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag,
    Symfony\Component\EventDispatcher\EventSubscriberInterface,
    Symfony\Component\HttpKernel\Event\GetResponseEvent,
    Symfony\Component\HttpKernel\KernelEvents;

class LegacySessionHandler implements EventSubscriberInterface
{
    /**
     * @var string The name of the bag name containing all the brunel values
     */
    const LEGACY_SESSION_BAG_NAME = 'old_app';

    /**
     * {@inheritdoc}
     */
    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::REQUEST => 'onKernelRequest'
        ];
    }

    /**
     * Transfer all the legacy session variables into a session bag, so $_SESSION['user_id'] will be accessible
     * via $session->getBag('old_app')->get('user_id'). The first bag name is defined as the class constant above
     *
     * @param GetResponseEvent $event
     */
    public function onKernelRequest(GetResponseEvent $event)
    {
        /** There might not be a session, in the case of the profiler / wdt (_profiler, _wdt) **/
        if (!isset($_SESSION))
        {
            return;
        }

        $session = $event->getRequest()->getSession();

        /** Only create the old_app bag if it doesn't already exist **/
        try
        {
            $bag = $session->getBag(self::LEGACY_SESSION_BAG_NAME);
        }
        catch (\InvalidArgumentException $e)
        {
            $bag = new NamespacedAttributeBag(self::LEGACY_SESSION_BAG_NAME);
            $bag->setName(self::LEGACY_SESSION_BAG_NAME);
            $session->registerBag($bag);
        }

        foreach ($_SESSION as $key => $value)
        {
            /** Symfony prefixes default session vars with an underscore thankfully, so ignore these **/
            if (substr($key, 0, 1) === '_' && $key !== self::LEGACY_SESSION_BAG_NAME)
            {
                continue;
            }

            $bag->set($key, $value);
        }
    }
}

正如下面的评论所解释的,这不一定是这样做的最佳方式。 但它的确有效。

会话变量是否有任何复杂的生命周期? 或者,一旦您登录到您的应用程序,它们主要是只读的?

如果后者适用,您可以将“hack”添加到事件订阅者中。 此订阅者将侦听交互式登录事件 ,它可能看起来像:

class PortSessionHandler implements EventSubscriberInterface
{
    private $session;

    public function __construct(SessionInterface $session) {
        $this->session = $session;
    }

    public static function getSubscribedEvents()
    {
        return [
            SecurityEvents::INTERACTIVE_LOGIN => [
                ['portLegacySession']
            ]
        ];
    }

    public function portLegacySession(InteractiveLoginEvent $event)
    {
        //here you could populate SF2 session with legacy session
        $this->session->set('user_id', $_SESSION['user_id']);
        ...
    }
}

希望这可以帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM