7

つまりね。私の同僚は、私たちが使用しているフレームワークのセッション処理を上書きしようとしています。このフレームワークはデフォルトでPHP独自のネイティブセッション処理を使用しますが、彼は現在、リクエスト間にデータベースレイヤーを実装しようとしています。

問題は、セッションが書き込まれるまでにデータベースオブジェクトが使用できなくなることですが、セッションからデータが読み取られるときなど、他の機能には使用できます。これはワイルドな振る舞いです。これが私たちがしたことです:

register_shutdown_function('exithandler'); 

session_set_save_handler(
    'sess_open',
    'sess_close',
    'sess_read',
    'sess_write',
    'sess_destroy',
    'sess_gc'
);

これらの各関数は、関数の名前で追跡できる1行をログファイルに書き込みます。これは、関数が呼び出されるたびに実行されます。ここで、要求される2つのURLを示します。1つはセッションが実際に書き込まれる場所(セッションへの新しいデータ)で、もう1つはセッションデータがチェックされるだけの場所(何も書き込まれない)です。これがパズルです:

/login/
sess_open
sess_read
exithandler
sess_write
sess_close

/account/
sess_open
sess_read
sess_write
sess_close
exithandler

この動作が異なるのはなぜですか?データがセッションに保存される前にexitハンドラーが呼び出されるのはなぜですか。また、同じメソッドが実際に呼び出されたとしても、通常のページでは同じことが当てはまらないのはなぜですか。

問題は、exithandlerが呼び出された後、どのクラスも使用できなくなることです。PHPガベージコレクターがすべてのクラスで__destruct()メソッドを呼び出し、それらがなくなったと思います。これは悪いことです。

PHPがこのように動作する理由を知っている人はいますか?

4

1 に答える 1

2

あなたのコメントがPHP5.4と言っているように、あなたはを見てみたいと思うかもしれませんSessionHandlerInterface()。メソッドにを渡してregister_shutdown_functionプロセスopen()を半自動化し、PHP5.4の機能を実際に活用することができます。

<?php
class MySessionHandler implements SessionHandlerInterface
{
    private $savePath;

    public function open($savePath, $sessionName)
    {
        register_shutdown_function('session_write_close');
        $this->savePath = $savePath;
        if (!is_dir($this->savePath)) {
            mkdir($this->savePath, 0777);
        }

        return true;
    }

    public function close()
    {
        return true;
    }

    public function read($id)
    {
        return (string)@file_get_contents("$this->savePath/sess_$id");
    }

    public function write($id, $data)
    {
        return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
    }

    public function destroy($id)
    {
        $file = "$this->savePath/sess_$id";
        if (file_exists($file)) {
            unlink($file);
        }

        return true;
    }

    public function gc($maxlifetime)
    {
        foreach (glob("$this->savePath/sess_*") as $file) {
            if (filemtime($file) + $maxlifetime < time() && file_exists($file)) {
                unlink($file);
            }
        }

        return true;
    }
}

$handler = new MySessionHandler();
session_set_save_handler($handler, true);
session_start();
于 2012-09-06T15:33:48.503 に答える