Symfony 2 和来自遗留应用程序的自定义会话变量 [英] Symfony 2 and custom session variables from legacy application

查看:49
本文介绍了Symfony 2 和来自遗留应用程序的自定义会话变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm in the process of setting up the ability to migrate from a Legacy codebase to a Symfony one, and I'm trying to share legacy session variables between the two applications.

我目前可以在 app_dev.phpvar_dump($_SESSION) 并且 user_id 键来自遗留应用程序.但是,当我在控制器中运行以下命令时,我没有得到任何会话变量:

I can currently var_dump($_SESSION) in app_dev.php and the user_id key comes through from the legacy application. However, when I run the following in a controller, I don't get any session variables:

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

澄清,我目前可以访问 $_SESSION['user_id'],所以会话在应用程序之间成功共享,但是 Symfony 会话对象和它的参数包不包含旧键.

So to clarify, I currently have access to $_SESSION['user_id'], so the session is shared between applications successfully, but the Symfony session object and it's parameter bags do not contain the legacy keys.

我的目标:

  • 为了使 user_id 键在 $request->getSession() 调用中可用
  • 要在此处提供所有其他密钥

我的问题:

我尝试过 PHP Session bridge 但我没有不认为这应该按照我的意愿行事.添加桥参数不仅不会在我的 Symfony 应用程序中执行任何操作,而且从我阅读的内容来看,这意味着以某种方式在另一个遗留应用程序中使用,而不是在 Symfony 中.

I have tried the PHP Session bridge but I don't think this is supposed to do what I want it to. Not only does adding the bridge parameter not do anything in my Symfony application, but from what I've read this is meant to be used somehow in the other legacy application, not in Symfony.

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

Symfony sessions store data like attributes in special 'Bags' which use a key in the $_SESSION superglobal. This means that a Symfony session cannot access arbitrary keys in $_SESSION that may be set by the legacy application, although all the $_SESSION contents will be saved when the session is saved. [From Integrating with legacy sessions]

我也看过TheodoEvolutionSessionBundle,但这是旧的,不是主动支持或工作,但不适用于 Symfony 3.

I've also taken a look at TheodoEvolutionSessionBundle, but this is old, isn't actively supported or worked on and doesn't work with Symfony 3.

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

I have noticed that Symfony stores it's session data under $_SESSION['_sf2_attributes'], so my initial thought was to do this in app_dev.php:

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

显然这样做是错误的,因为我还必须在那里调用 session_start().

This is clearly the wrong way to do this, as I also have to call session_start() in there as well.

如何将遗留的 $_SESSION 数据迁移到 Symfony 的 Session 对象中? Symfony 是否有内置的东西来帮助解决这个问题或提供一个包?如果没有,哪里可以将我的自定义 $_SESSION['_sf2_attributes'] 'hack' 放置在正确的位置以处理所有这些密钥的迁移?

How can I migrate legacy $_SESSION data into Symfony's Session object? Is there something built-in to Symfony to help with this or a bundle available? If there isn't, where can I place my custom $_SESSION['_sf2_attributes'] 'hack' in the correct place to handle the migration of all these keys?

推荐答案

Symfony 在会话中引入了会话包的概念,所以一切都是命名空间的.没有内置解决方案来访问非命名空间会话属性.

Symfony introduces a concept of session bags into the session, so everything is namespaced. There's no build in solution to access non-namespaced session attributes.

解决方案是使用标量包,就像 TheodoEvolutionSessionBundle 所做的那样.我不会直接使用它,而是实现一些对你的项目有用的自定义东西(他们只为 symfony1 和 codeigniter 提供集成).以他们的想法为基础,但要根据您的需要进行调整.

The solution is to use scalar bags, just like TheodoEvolutionSessionBundle does. I wouldn't use it directly, but implement something custom that will work for you project (they only provide integrations for symfony1 and codeigniter anyway). Base it on their idea, but adapt it to your needs.

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

Alternatively, you could implement a kernel.request listener that would rewrite legacy session attributes to the Symfony one:

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

吉姆的编辑

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

I created an event listener on kernel.request - every request that comes in, we loop through all the legacy session vars in $_SESSION and place them in Symfony's session bag. Here's the listener:

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);
        }
    }
}

正如下面的评论中所解释的,这不一定是最好的方法.但它有效.

As explained in the comments below, this isn't necessarily the best way of doing this. But it works.

这篇关于Symfony 2 和来自遗留应用程序的自定义会话变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆