[英]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.