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