5

默认的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);

运行后如下图所示:
图片描述

默认是session_start分别调用的回调函数。为open read ,然后等待脚本结束,收集$_SESSION(默认在内存中),然后关闭脚本,然后执行write,写入文件,然后close。

改变默认session回调顺序

那么我们使用 session_commit(); 或者 session_write_close();函数调用的时候,session的机制就改变了,直接写入文件,关闭文件。然后再执行脚本。如下图所示:
session顺序机制

那么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的回调函数流程执行顺序

在win平台的遗留问题(已经测试解决)

ps:由于都是在win上测试,可能对gc的回收不是很准确,包括即使我设置为1:1,百分之百回收。在win上仍然存在这个sessionid文件,可能原因是session 锁机制,我在linux上测试了再分享给大家。
另外session的相关也可参考
该问题已经澄清,请移步php Session gc机制下在window下与ununtu是不同的。


牙小木木
1.5k 声望80 粉丝

iamtb.cn