【问题标题】:Why i cant set session var in __destruct() method?为什么我不能在 __destruct() 方法中设置会话变量?
【发布时间】:2016-08-26 14:39:48
【问题描述】:

我尝试在 __destruct() 方法中设置会话变量。 方法 __destruct() 正在运行,但未设置会话变量。 同时,__contruct() 中的会话或其他方法(例如 test())按预期工作。

public function test()
{
    $_SESSION['MyVarTest'] = rand(200,300); ← working correctly
}

public function __destruct()
{
    echo 'called';
    $_SESSION['MyVar'] = rand(1,100); ← not working
}

更新版本。现在我尝试原生 PHP Session 和 Symfony 组件,但都不能在 __destruct() 方法中工作。

<?php

namespace Project\Modules\Cart\Storage;

use Illuminate\Support\Collection;

class Session
{

    /**
     * @var \Symfony\Component\HttpFoundation\Session\Session
     */
    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
    }

}

【问题讨论】:

  • 向我们展示你是如何测试这一切的。
  • 你怎么知道__destruct() 确实被调用了?
  • 是的,这个例子还远未完成。我能想到一个问题:如何停止脚本?最好是一个完整的例子,我们可以运行。
  • var_dump($this-&gt;session) in __destruct
  • 您可能还应该包含更多代码 - 您只展示了类中的几个方法。我尝试使用一些类似的代码复制您的代码 - 在我的示例中,我发现在创建对象之后,然后 unset() 调用了 __destruct() 并设置了会话密钥。

标签: php symfony session session-set-save-handler


【解决方案1】:

Symfony 会话使用自定义会话处理程序。 (通过session_set_save_handler

自定义会话处理程序导致 PHP 注册一个关闭函数(即register_shutdown_function),调用session_register_shutdown,它添加另一个关闭处理程序(因此它将最后执行),调用session_write_close,然后有效地关闭您的会话。

调用该函数后,将不再存储任何写入内容。 [因为会话处理程序之后将不再被调用。]

并且由于(尚未清理的对象的)析构函数仅在调用关闭函数之后运行,因此此会话写入将失败。

避免这种情况的唯一解决方案是不使用自定义会话处理程序(我猜你不是一个选项),手动重新启动会话(只要破坏顺序不首先破坏类),或者显式销毁所有在关闭处理程序或之前对此对象的引用。

【讨论】:

  • 对不起,但我不明白,我应该怎么做才能解决我的问题。你能帮帮我吗?
  • 好吧,你无法真正修复这种行为。你必须解决它。要么避免在 __destruct 中设置 $_SESSION,要么确保受影响的对象在最后一个关闭函数之前被销毁(例如,通过显式 unset()'ing)。您的应用程序中究竟需要做什么取决于您的代码。你必须自己弄清楚。
  • 我真的明白这种行为会创建 Symfony 的 Session 组件?
  • 因为,当使用原生 PHP 时,这个问题不存在:3v4l.org/5FCFF。我是对的?
  • @Stanislav 这个例子有缺陷。 $_SESSION 超全局仍然存在,对它的更改将不会出现在下一个请求中。但是,是的,对于原生 PHP,只要不调用 session_set_save_handler(),问题就不存在了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-08
  • 1970-01-01
相关资源
最近更新 更多