簡體   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