3

更新:解決済み

私はついに自分の問題を理解しました(私は思います)。問題は、クロージャーをシリアル化できないこと、つまり、クロージャーをセッションに保存できないことだと確信しています。次の問題は、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ファイルが開かれなかったため(私の関数がセッションの開きを引き継いだため)、もちろん失敗します。セッションにクロージャを保存すると、なぜそのような復帰が発生するのか、またはこれが一般的に壊れているのか、私にはわかりません。どんな助けでもいただければ幸いです。

4

1 に答える 1

0

SuperClosureこれは、Jeremy Lindblomの を使用して実現できるようになりました。パッケージは彼の github にあります: https://github.com/jeremeamia/super_closure

于 2014-07-22T14:17:59.043 に答える