Session PHP:在会话中存储闭包会中断会话

Session PHP:在会话中存储闭包会中断会话,session,mysqli,php,Session,Mysqli,Php,更新:已解决 (我想)我终于解决了我的问题。我很确定问题在于闭包不能序列化,这意味着它们不能存储在会话中。接下来的问题是PHP没有返回一个非常有用的错误,并以一种意外的方式中断,而不是告诉我无法序列化闭包 我将会话数据存储在mysql数据库中。我已经准备好了我的应用程序的这一部分,并且很好地工作了很长一段时间。今天,我试图在会话中存储一个闭包(即匿名函数),这破坏了我原本表现良好的会话 我的会话管理由一个对象处理,当PHP试图销毁该对象时,该对象会自动调用session_write_close

更新:已解决

(我想)我终于解决了我的问题。我很确定问题在于闭包不能序列化,这意味着它们不能存储在会话中。接下来的问题是PHP没有返回一个非常有用的错误,并以一种意外的方式中断,而不是告诉我无法序列化闭包


我将会话数据存储在mysql数据库中。我已经准备好了我的应用程序的这一部分,并且很好地工作了很长一段时间。今天,我试图在会话中存储一个闭包(即匿名函数),这破坏了我原本表现良好的会话

我的会话管理由一个对象处理,当PHP试图销毁该对象时,该对象会自动调用session_write_close()。我这样做是因为,否则,当PHP试图关闭会话时,我的数据库连接(mysqli对象)已经被破坏

我接管了会话处理,如下所示:

// set the session save handler
session_set_save_handler(
    array( $this, '_open' ),
    array( $this, '_close' ),
    array( $this, '_read' ),
    array( $this, '_write' ),
    array( $this, '_destroy' ),
    array( $this, '_clean' )
);
这是相当标准的。处理会话关闭的部分如下所示:

public function __destruct()
{
    // this variable will only be destroyed when the script is closing
    // at this point it is safe to close the session
    // if we wait for php to close the session then we will
    // have lost the database connection, so we do it now

    session_write_close();
}

// write session data
public function _write( $sid, $data )
{
    // run query to write to database
    $now = NOW;
    $stmt = $this->mysqli->prepare( "REPLACE INTO $this->table (sid,time,data) VALUES (?,?,?)" );
    $stmt->bind_param( 'sis', $sid, $now, $data );

    // execute
    $success = $stmt->execute();

    // close
    $stmt->close();

    // and return
    return $success;
}

// close session store
public function _close()
{
    // close the database connection
    $this->mysqli->close();

    return true;
}
几个print函数表明,通常情况下,这与您所想的一样:调用u destruct()函数,调用会话_write _close(),然后立即调用_write()和_close()。但是,在我存储会话结束的那一刻:

$test = function($name)
{
    print "Hello $name";
};

$_SESSION['test'] = $test;
一切都破裂了__destruct()像以前一样被调用,但执行永远不会到达_write()或_close()函数。相反,我得到了以下信息:

警告:会话写入关闭()[函数.会话写入关闭]:无法写入会话数据(用户)。请验证第48行/var/www/vhosts/ambida.com/httpdocs/includes/core/session_handler.php中session.save_path的当前设置是否正确(/var/lib/php/session)

致命错误:在第0行未知的堆栈帧中引发异常


这真的毫无意义。看起来它已经恢复到默认会话处理程序,这当然会失败,因为tmp文件从未打开(因为我的函数接管了打开会话)。我不明白为什么在会话中存储一个闭包会导致这样的恢复,或者为什么这通常会中断。任何帮助都将不胜感激。

现在可以通过使用Jeremy Lindblom提供的
超级闭合
来实现。包可以在他的Github上找到:

如果您已经解决了问题,请考虑添加实际的解决方案并标记为接受,以便其他人可以受益。您可以将解决方案作为答案并接受吗?谢谢