原创

php session基本原理解析

温馨提示:
本文最后更新于 2018年06月26日,已超过 2,124 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

该类实现了php session的基本原理操作

由于session比较简单,直接封装出了session的基本操作

<?php
/**
 * Created by PhpStorm.
 * User: 10671
 * Date: 2018/6/22
 * Time: 23:48
 */

class SessionHandle
{

    private static $_instance;

    private $config = array(
        'cookie_name' => 'session_id',
        'cookie_path' => '',
        'cookie_domain' => '',
        'cookie_secure' => false,

        'save_path' => __DIR__ . DIRECTORY_SEPARATOR . 'runtime' . DIRECTORY_SEPARATOR,//保存路径
        'save_path_num' => 5,//保存目录数(以免造成一个目录太多session文件,0则保存在当前目录)

        'cache_expire' => 30 * 60,//过期时间
        'session_handler' => null,
        'gc_probability' => 1//触发垃圾回收概率1/100
    );

    public $path_dictionary = array(
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
    );

    public function __construct($config = array())
    {
        foreach ($config as $key => $value) {
            if (isset($this->config[$key])) {
                $this->config[$key] = $value;
            }
        }
        
    }
    
        public function __destruct()
        {
            $this->saveSession();
        }


    /**
     * 单例
     * @return SessionHandle
     */
    public static function getInstance($config=array())
    {
        if (!(self::$_instance instanceof self)) {
            self::$_instance = new static($config); //new static和new self区别可查看http://www.jb51.net/article/54167.htm
        }
        return self::$_instance;
    }

    /**
     * 开始设置session
     */
    public function startSession($session_id = null)
    {
        if (is_callable($this->config['session_handler'])) {
            return $this->config['session_handler']('start_session');
        }
        if (mt_rand(1, 100) <= $this->config['gc_probability']) {
            $this->gc();
        }
        if (!isset($_COOKIE[$this->config['cookie_name']])) {
            $session_id === null && $session_id = $this->getSessionId();
            $this->setCookie($session_id);
            $this->saveSessionData($session_id, array());
        } else {
            $session_id = $_COOKIE[$this->config['cookie_name']];
        }
        return $data = $_SESSION = $this->getSessionData($session_id);
    }

    /**
     * 设置
     * @param $session_id
     * @param $name
     * @param $value
     */
    public function setSession($name, $value, $session_id = null)
    {
        $session_id === null && $session_id = $this->getSessionId();
        $data = $this->getSessionData($session_id);
        if (empty($name)) {
            return false;
        }
        if ($value == null) {
            unset($data[$name]);
        }
        $data[$name] = $value;
        $result = $this->saveSessionData($session_id, $data);
        if ($result === false) {
            return $result;
        }
        return $_SESSION = $data;
    }

    /**
     * 保存数据到文件
     * @param null $session_id
     * @param null $data
     * @return bool|int|null
     */
    public function saveSession($session_id=null,$data=null){
        $session_id === null && $session_id = $this->getSessionId();
        $data === null && $data = $_SESSION;
        if (is_callable($this->config['session_handler'])) {
            return $this->config['session_handler']('save_session', $session_id);
        }
        $result = $this->saveSessionData($session_id, $data);
        if ($result === false) {
            return $result;
        }
        return $_SESSION = $data;
    }

    /**
     * 删除
     * @param null $session_id
     * @return bool
     */
    public function deleteSession($session_id = null)
    {
        $session_id === null && $session_id = $this->getSessionId();
        $result = $this->deleteSessionData($session_id);
        $this->setCookie('');
        $_SESSION = array();
        return $result;
    }

    /**
     * 设置cookie
     * @param $session_id
     */
    public function setCookie($session_id)
    {
        setcookie($this->config['cookie_name'], $session_id, time() + $this->config['cache_expire'], $this->config['cookie_path'], $this->config['cookie_domain'], $this->config['cookie_secure']);
    }

    /**
     * 获取session_id
     * @param $session_id
     * @return mixed
     */
    public function getSessionData($session_id)
    {
        if (is_callable($this->config['session_handler'])) {
            return $this->config['session_handler']('read', $session_id);
        }
        $this->updateSessionIndex($session_id);
        $data = serialize(array());
        if (file_exists($this->getSessionIDPath($session_id))) {
            $data = file_get_contents($this->getSessionIDPath($session_id));
        }
        return unserialize($data);
    }

    /**
     * 修改保存
     * @param $session_id
     * @param $data
     * @return bool|int
     */
    public function saveSessionData($session_id, $data)
    {
        if (is_callable($this->config['session_handler'])) {
            return $this->config['session_handler']('save', $session_id, $data);
        }
        $this->updateSessionIndex($session_id);
        $result = file_put_contents($this->getSessionIDPath($session_id), serialize($data));
        return $result;
    }

    /**
     * 删除文件
     * @param $session_id
     * @return bool
     */
    public function deleteSessionData($session_id)
    {
        if (is_callable($this->config['session_handler'])) {
            return $this->config['session_handler']('delete', $session_id);
        }
        return unlink($this->getSessionIDPath($session_id));
    }

    /**
     * 设置session处理
     * @param callable $function
     */
    public function setSessionHandler(callable $function)
    {
        $this->config['session_handler'] = $function;
    }

    /**
     * 获取sessionid的路径
     * @param $session_id
     * @return string
     */
    public function getSessionIDPath($session_id)
    {
        if (abs($this->config['save_path_num']) == 0) {
            $path = $this->config['save_path'];
        } else {
            $path = $this->config['save_path'] . $this->path_dictionary[$this->time33($session_id) % $this->config['save_path_num']] . DIRECTORY_SEPARATOR;
        }
        if (!is_dir($path)) {
            @mkdir($path);
        }
        return $path . $session_id;
    }

    /**
     * 垃圾回收
     * @return bool|int
     */
    public function gc()
    {
        if (is_callable($this->config['session_handler'])) {
            return $this->config['session_handler']('gc');
        }
        if ($this->config['cache_expire'] <= 0) {
            return true;
        }
        $session_index_path = $this->config['save_path'] . 'index';
        $session_index = unserialize(file_get_contents($session_index_path));
        foreach ($session_index as $session_id => $value) {
            if ($value + $this->config['cache_expire'] < time()) {
                unset($session_index[$session_id]);
                @unlink($this->deleteSessionData($session_id));
            }
        }
        $result = file_put_contents($session_index_path, serialize($session_index));
        return $result;
    }

    /**
     * 更新session索引
     * @param null $session_id
     */
    public function updateSessionIndex($session_id = null)
    {
        if (is_callable($this->config['session_handler'])) {
            return $this->config['session_handler']('update_session_index', $session_id);
        }
        if ($this->config['cache_expire'] <= 0) {
            return true;
        }
        $session_id === null && $session_id = $this->getSessionId();
        $session_index_path = $this->config['save_path'] . 'index';
        $session_index = array();
        if (file_exists($session_index_path)) {
            $session_index = unserialize(file_get_contents($session_index_path));
        }
        $session_index[$session_id] = time();
        $result = file_put_contents($session_index_path, serialize($session_index));
        return $result;
    }

    /**
     * 生成一个尽量唯一的字符串
     */
    public function getSessionId()
    {
        $session_id = null;
        if (isset($_COOKIE[$this->config['cookie_name']])) {
            $session_id = $_COOKIE[$this->config['cookie_name']];
        }
        if (empty($session_id)) {
            if (is_callable($this->config['session_handler'])) {
                return $this->config['session_handler']('create_session_id');
            }
            $key = uniqid(mt_rand(100000, 999999));
            $session_id = $this->md5($key);
        }
        return $session_id;
    }

    public function md5($str)
    {
        $hash = md5($str);
        return $hash;
    }

    public function time33($str)
    {
        $hash = 0;
        $s = md5($str);
        $len = 32;
        for ($i = 0; $i < $len; $i++) {
            $hash = ($hash * 33 + ord($s{$i})) & 0x7FFFFFFF;
        }
        return $hash;
    }
}

该类实现了php基本的session原理

调用方法:

include 'SessionHandle.php';

$session_handle = SessionHandle::getInstance();
//var_dump($session_handle);
$session_handle->startSession();
//$session_handle->deleteSession();
//$session_handle->setSession('name','ncl');
var_dump($_SESSION);
正文到此结束
本文目录