我所理解的session_set_save_handler的執行順序機制


默認的session handler啓動順序

<?php

ini_set('session.gc_maxlifetime',10);

ini_set('session.gc_probability ' ,1);

ini_set('session.gc_divisor',5 );
class FileSessionHandler
{
    private $savePath;

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

        echo __FUNCTION__."<BR>";
        return true;
    }

    function close()
    {
        echo __FUNCTION__."<BR>";
        return true;
    }

    function read($id)
    {
        echo __FUNCTION__."<BR>";
        return (string)@file_get_contents("$this->savePath/sess_$id");
    }

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

    function destroy($id)
    {
        $file = "$this->savePath/sess_$id";
        if (file_exists($file)) {
            unlink($file);
        }
        echo __FUNCTION__."<BR>";
        return true;
    }

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


    function end(){
        echo '我是最後腳本結束register_shutdown_functiond調用'."<br>";
    }
}

$handler = new FileSessionHandler();
session_set_save_handler(
    array($handler, 'open'),
    array($handler, 'close'),
    array($handler, 'read'),
    array($handler, 'write'),
    array($handler, 'destroy'),
    array($handler, 'gc')
    );
// 下面這行代碼能夠防止使用對象做爲會話保存管理器時可能引起的非預期行爲
register_shutdown_function(array($handler,end));

    
session_start();
$_SESSION['name']='tb';
// session_commit();
// session_write_close(); // 若是開啓,那順序就是open read  (gc) write close
// session_destroy();
// session_regenerate_id(true);

運行後以下圖所示:
圖片描述php

默認是session_start分別調用的回調函數。爲open read ,而後等待腳本結束,收集$_SESSION(默認在內存中),而後關閉腳本,而後執行write,寫入文件,而後close。linux

改變默認session回調順序

那麼咱們使用 session_commit(); 或者 session_write_close();函數調用的時候,session的機制就改變了,直接寫入文件,關閉文件。而後再執行腳本。以下圖所示:
session順序機制segmentfault

那麼session_dessory調用的時候,就是在read以後,由於只要sesson_start開啓,先執行的就是open 和read。
那麼gc呢,咱們都知道gc是根據 session.gc_probabilitysession.gc_divisor 參數控制。本例中我設置了他們的比例爲5,可是如今的問題是我刷新5+次可能也調用不了一次gc。可能和個人win平臺有關係。若是命中gc,並且沒有調用 session_commit(); 或者 session_write_close();函數,運行流程以下圖所示:
session的回調函數流程執行順序session

在win平臺的遺留問題(已經測試解決)

ps:因爲都是在win上測試,可能對gc的回收不是很準確,包括即便我設置爲1:1,百分之百回收。在win上仍然存在這個sessionid文件,可能緣由是session 鎖機制,我在linux上測試了再分享給你們。
另外session的相關也可參考
該問題已經澄清,請移步php Session gc機制下在window下與ununtu是不一樣的。函數

相關文章
相關標籤/搜索