我尝试在__destruct()方法中设置会话变量。__destruct()方法正在运行,但未设置会话变量。同时,会话在__construct()或其他方法(例如test())中按预期工作。
public function test()
{
$_SESSION['MyVarTest'] = rand(200,300); ← working correctly
}
public function __destruct()
{
echo 'called';
$_SESSION['MyVar'] = rand(1,100); ← not working
}
更新版本。现在我尝试本地PHP会话和Symfony组件,都不能在__destruct()方法中工作。
<?php
namespace ProjectModulesCartStorage;
use IlluminateSupportCollection;
class Session
{
/**
* @var SymfonyComponentHttpFoundationSessionSession
*/
protected $session;
protected $cart;
public function __construct()
{
$this->cart = new Collection();
$this->session = app('session');
print_r($_SESSION);
}
public function test()
{
$this->session->set('json', rand(1,100)); ← working correctly
$_SESSION['json'] = rand(1,100); ← working correctly
return $this->cart->toJson();
}
public function __destruct()
{
echo 'called';
$_SESSION['MyVar'] = rand(1,100); ← not working
$this->session->set('cart', serialize($this->cart->toArray())); ← not working
}
}
Symfony会话使用自定义会话处理程序。(via session_set_save_handler
)
自定义会话处理程序导致PHP注册一个关闭函数(即register_shutdown_function
),调用session_register_shutdown
,它添加另一个关闭处理程序(因此它将最后执行),调用session_write_close
,然后有效地关闭您的会话。
调用该函数后,不再存储进一步的写操作。[因为会话处理程序之后将不再被调用]
并且由于析构函数(对象尚未清理)在关闭函数被调用后只运行,因此此会话写入将失败。
避免这种情况的唯一解决方案是不使用自定义会话处理程序(我猜不是您的选项),手动重新启动会话(只要销毁顺序不首先销毁类),或者在关闭处理程序或之前显式地销毁对该对象的所有引用。