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

时间:2012-12-07 18:03:01

标签: session mysqli php

  

更新:已解决

     

我终于找到了问题(我想)。我很确定问题是闭包无法序列化,这意味着它们无法存储在会话中。接下来的问题是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;
}

一些打印函数显示通常这可以像您想象的那样工作:调用__destruct()函数,调用session_write_close(),紧接着调用_write()和_close()。但是,当我将闭包存储到会话时:

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

$_SESSION['test'] = $test;

一切都破了。像以前一样调用__destruct(),但执行永远不会到达_write()或_close()函数。相反,我得到这些消息:

  

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

     

致命错误:在第0行的“未知”中没有堆栈帧的情况下抛出异常

这真的没有意义。看起来它已经恢复到默认会话处理程序,这当然会失败,因为tmp文件从未打开过(因为我的函数接管了打开会话)。我不明白为什么在会话中存储闭包会导致这种恢复发生,或者为什么这种情况一般会破裂。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

现在可以使用Jeremy Lindblom的SuperClosure来实现。该软件包可以在他的github上找到:https://github.com/jeremeamia/super_closure