我有一个旧版 API 应用程序,它可以生成传统的
session_start();
并将数据填充到 $_SESSION
中。$_SESSION
。
我发现与遗留应用程序集成。
我不知道遗留应用程序是否有提到的
own PHP save handler
,我只是尝试了所有可能的配置组合。
framework:
session:
storage_factory_id: session.storage.factory.php_bridge
我取下了
var/cache
并加热了它。
结果:
$_SESSION
:未定义$this->requestStack->getSession()
:给出一个复杂的对象树,没有遗留会话数据,但带有空数组的奇怪 Symfony 键_sf2_attributes
,_symfony_flashes
。$this->requestStack->getSession()->get('keyInLegacySession')
:空framework:
session:
storage_factory_id: session.storage.factory.php_bridge
handler_id: ~
我取下了
var/cache
并加热了它。
结果:同上。
framework:
session:
storage_factory_id: session.storage.factory.php_bridge
handler_id: session.handler.native_file
我取下了
var/cache
并加热了它。
结果:同上。
我尝试按照https://stackoverflow.com/a/44145831/4840661中的说明进行调试,错误遗留和Symfony给出相同的ini设置。
有什么想法如何使用 Symfony 读取我的案例中的遗留会话数据吗?
我会尝试以下方法:
您可以在 Symfony 中创建自定义会话处理程序。
例如,您创建
CustomNativeSessionStorage
处理程序并继承 NativeSessionStorage
处理程序。当然,您也可以采用其他现有的处理程序并自定义它们。
在
CustomNativeSessionStorage::start()
方法中,您可以定义会话启动或加载的方式和时间。您当然可以使用 NativeSessionStorage::start() 的一部分来实现此目的。
NativeSessionStorage::start()
方法用于启动会话,然后您可以自己控制。
namespace App\Session;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
class CustomNativeSessionStorage extends NativeSessionStorage
{
public function start(): bool
{
// Here is your logic
return true;
}
}
framework:
session:
# ...
handler_id: App\Session\CustomNativeSessionStorage
我发现自己处于同样的场景,我最终归档了这两个功能:
<?php
namespace App\Session;
use LogicException;
use Override;
use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
use Symfony\Component\HttpFoundation\Session\SessionBagProxy;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
/**
* This class integrates legacy session data with Symfony's AttributeBag ('_sf2_attributes').
* Symfony groups its session data under specific $_SESSION keys (e.g., '_sf2_attributes').
* The structure of the $_SESSION array is as follows:
*
* $_SESSION = [
* // Legacy app's data, ungrouped:
* PHPSESSID = <value>,
* <key> = <value>,
* ...more values
* // Symfony session data, grouped:
* '_sf2_attributes' => [...],
* '_sf2_meta' => [...],
* '_symfony_flashes' => [...],
* ]
*
* NativeSessionStorage->loadSession() doesn't load the legacy data, and NativeSessionStorage->save() removes it.
* Therefore, the aims of this class are:
* - Integrate the data coming from the legacy app into the AttributeBag '_sf2_attributes'.
* - Preserve the legacy app's ungrouped $_SESSION data to avoid breaking its session.
*/
class LegacySessionStorage extends NativeSessionStorage
{
#[Override]
protected function loadSession(?array &$session = null): void
{
parent::loadSession($session);
// Filter legacy session data (keys not starting with '_s')
$legacySessionData = array_filter($_SESSION, fn ($key) => !str_starts_with($key, '_s'), ARRAY_FILTER_USE_KEY);
// Retrieve and validate the 'attributes' bag
$attributesBagProxy = $this->getBag('attributes');
if (!$attributesBagProxy instanceof SessionBagProxy) {
throw new LogicException('Expected SessionBagProxy object, but found ' . get_class($attributesBagProxy));
}
$attributesBag = $attributesBagProxy->getBag();
if (!$attributesBag instanceof AttributeBag) {
throw new LogicException('Expected AttributeBag object, but found ' . get_class($attributesBag));
}
// Merge legacy data into Symfony's '_sf2_attributes'
foreach ($legacySessionData as $key => $value) {
$attributesBag->set($key, $value);
}
}
}
要使其工作,您需要一个特定的工厂类:
<?php
namespace App\Session;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorageFactory;
use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
class LegacySessionStorageFactory extends NativeSessionStorageFactory
{
private array $options;
private AbstractProxy|\SessionHandlerInterface|null $handler;
private ?MetadataBag $metaBag;
private bool $secure;
public function __construct(array $options = [], AbstractProxy|\SessionHandlerInterface|null $handler = null, ?MetadataBag $metaBag = null, bool $secure = false)
{
$this->options = $options;
$this->handler = $handler;
$this->metaBag = $metaBag ?? new MetadataBag();
$this->secure = $secure;
}
public function createStorage(?Request $request): SessionStorageInterface
{
$storage = new LegacySessionStorage($this->options, $this->handler, $this->metaBag);
if ($this->secure && $request?->isSecure()) {
$storage->setOptions(['cookie_secure' => true]);
}
return $storage;
}
}
并将其注册到
framework.yml
:
session:
storage_factory_id: session.storage.factory.legacy
handler_id: ~