Symfony 2 и пользовательские переменные сеанса из унаследованного приложения

Я в процессе настройки возможности перехода из кодовой базы Legacy на Symfony, и я пытаюсь использовать устаревшие переменные сеанса между двумя приложениями.

В настоящее время я могу var_dump($_SESSION) в app_dev.php а ключ app_dev.php из user_id приложения. Однако, когда я запускаю следующее в контроллере, я не получаю никаких переменных сеанса:

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

Поэтому, чтобы уточнить , у меня в настоящее время есть доступ к $_SESSION['user_id'] , поэтому сеанс распределяется между приложениями успешно, но объект сеанса Symfony и его пакеты параметров не содержат устаревших ключей.

Моя цель:

  • Чтобы ключ user_id был доступен в вызове $request->getSession()
  • Для всех остальных ключей, которые будут доступны здесь

Мои проблемы:

Я пробовал мост PHP Session, но я не думаю, что это должно делать то, что я хочу. Не только добавление параметра моста ничего не делает в моем приложении Symfony, но из того, что я прочитал, это должно использоваться как-то в другом унаследованном приложении, а не в Symfony.

В сеансах Symfony хранятся данные, такие как атрибуты в специальных «сумочках», которые используют ключ в суперзвезде $ _SESSION. Это означает, что сеанс Symfony не может получить доступ к произвольным ключам в $ _SESSION, которые могут быть установлены устаревшим приложением, хотя все содержимое $ _SESSION будет сохранено при сохранении сеанса. [От интеграции с предыдущими сеансами ]

Я также посмотрел на TheodoEvolutionSessionBundle , но он старый, не активно поддерживается или работает и не работает с Symfony 3.

Я заметил, что Symfony хранит данные сеанса в $_SESSION['_sf2_attributes'] , поэтому моя первоначальная мысль заключалась в том, чтобы сделать это в app_dev.php :

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

Очевидно, это неправильный способ сделать это, так как мне также нужно вызвать session_start() .

Как переносить устаревшие данные $ _SESSION в объект Session Symfony? Есть ли что-то встроенное в Symfony, чтобы помочь с этим или пакетом? Если этого не происходит, где я могу поместить свой пользовательский $_SESSION['_sf2_attributes'] 'hack' в $_SESSION['_sf2_attributes'] место, чтобы обработать миграцию всех этих ключей?

Symfony вводит концепцию сессионных мешков в сессию, поэтому все пространство имен. Там нет встроенного решения для доступа к атрибутам сеанса, не связанным с именами.

Решение заключается в использовании скалярных пакетов, как это делает TheodoEvolutionSessionBundle . Я бы не использовал его напрямую, а реализовал что-то индивидуальное, которое будет работать для вас проекта (они только обеспечивают интеграцию для symfony1 и codeigniter в любом случае). Основывайте их на своей идее, но приспосабливайте ее к вашим потребностям.

Кроме того, вы можете реализовать прослушиватель kernel.request , который переписывал бы устаревшие атрибуты сеанса на Symfony:

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

Редактирование Джима

Я создал прослушиватель событий на kernel.request – каждый запрос, который приходит, мы прокручиваем все устаревшие сессии vars в $_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); } } } 

Как поясняется в комментариях ниже, это не обязательно лучший способ сделать это. Но это работает.

Существует ли какой-либо сложный жизненный цикл для ваших переменных сеанса? Или они в основном доступны для чтения только после входа в ваше приложение?

Если последнее применимо, вы можете добавить этот «взлом» в подписчика событий. Этот абонент будет прослушивать интерактивное входное событие , и он может выглядеть примерно так:

 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']); ... } } 

Надеюсь это поможет