Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
基于PHP数据库的会话数据_Php_Mysql_Session - Fatal编程技术网

基于PHP数据库的会话数据

基于PHP数据库的会话数据,php,mysql,session,Php,Mysql,Session,我正在尝试设计一个会话处理程序,它使用数据库来存储详细信息 其中一点是,如果当前正在使用会话数据,那么我不希望加载它们(直到第一个脚本完成并更新数据) 我有一个基本的类来完成这项工作,它似乎正在工作,下面是一个小测试脚本:- <?php class MySessionHandler implements SessionHandlerInterface { private $db = null; public function open($savePath, $sess

我正在尝试设计一个会话处理程序,它使用数据库来存储详细信息

其中一点是,如果当前正在使用会话数据,那么我不希望加载它们(直到第一个脚本完成并更新数据)

我有一个基本的类来完成这项工作,它似乎正在工作,下面是一个小测试脚本:-

<?php

class MySessionHandler implements SessionHandlerInterface
{

    private $db = null;

    public function open($savePath, $sessionName)
    { 
        $host = 'localhost';
        $user = 'root';
        $pass = '';
        $name = 'em_sessions';
        $this->db = new mysqli($host, $user, $pass, $name);
        return true;
    }

    public function close()
    {
        return true;
    }

    public function read($session_key)
    {
        $this->db->autocommit(FALSE);

        if($stmt = $this->db->prepare("SELECT data FROM sessions WHERE session_key = ? FOR UPDATE"))
        {
            $stmt->bind_param('s', $session_key);
            $stmt->execute();
            echo $stmt->error." - ".$stmt->errno."<br />";
            $retry = 0;
            while ($stmt->errno == 1213 and $retry++ < 20)
            {
                usleep(50);
                $stmt->execute();
                echo $stmt->error." - ".$stmt->errno."<br />";
            }
            $stmt->store_result();
            $stmt->bind_result($data);
            $stmt->fetch();
        }
        else
        {
            echo "Unable to prepare statement ".$this->db->error."<br />";
        }
        return $data;
    }

    public function write($session_key, $data)
    {

        $time = time();
        if($stmt = $this->db->prepare("INSERT INTO sessions (set_time, data, session_key) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE set_time=VALUES(set_time), data=VALUES(data)"))
        {
            echo "Written(".time().")<br />";
            $stmt->bind_param('iss', $time, $data, $session_key);
            $stmt->execute();

            $this->db->commit();
        }
        else
        {
            echo "Unable to prepare statement ".$this->db->error."<br />";
        }
        return true;
    }

    public function destroy($session_key)
    {
        if($stmt = $this->db->prepare("DELETE FROM sessions WHERE session_key = ?"))
        {
            $stmt->bind_param('s', $session_key);
            $stmt->execute();
        }
        else
        {
            echo "Unable to prepare statement ".$this->db->error."<br />";
        }
        return true;
    }

    public function gc($maxlifetime)
    {
        if($stmt = $this->db->prepare("DELETE FROM sessions WHERE set_time < ?"))
        {
            $old = time() - $max;
            $stmt->bind_param('s', $old);
            $stmt->execute();
        }
        else
        {
            echo "Unable to prepare statement ".$this->db->error."<br />";
        }
        return true;
    }

}

$handler = new MySessionHandler();
session_set_save_handler($handler, true);
session_start();
echo session_id()."<br />";

echo "<a href='http://localhost/TestArea/session_test.php'>Do Me</a><br />";

if (!array_key_exists('cnt', $_SESSION))
{
    echo "No session cnt found so initialising<br />";
    $_SESSION['cnt'] = 0;
}

echo "Page called ".++$_SESSION['cnt']." times (".time().")<br />";

sleep(2);

session_write_close();

sleep(2);

echo "Ended(".time().")<br />";

这是一个有趣的问题,这里有一个长期的尝试,试图找出问题可能是什么——检查您是否正在执行流水线HTTP请求。您还没有说您使用了哪种浏览器或哪台服务器有问题,可能他们正在管道传输HTTP请求,这将把责任转移到与您怀疑的完全不同的部分(这部分是浏览器Web服务器通信,而不是您的脚本)。如果你能查出来并排除它(除非是罪魁祸首),那将有助于进一步调试。@N.B.-为这个想法干杯。它似乎与浏览器无关,其行为与Opera、Chrome和Firefox中的行为相同。就服务器而言,它在我的Windows机器上的WAMP服务器上以及上传到Linux机器上时的行为都是相同的。然而,它已经触发我尝试其他东西。我还保存了脚本的开始时间(在会话开始之前)并将其输出。当第一次运行完成时,脚本的第二次和后续运行具有此开始时间。似乎整个脚本都被阻止了,不仅仅是会话。是的,这就是管道的作用。这是Apache的默认行为。排除这种情况的一种方法是实际执行来自两台不同机器(所有不同管道)的请求。我之所以提出这个建议,是因为我在下载一个文件时遇到了一个问题,我以前一直在编码这个文件。这很奇怪,因为我不能一次下载两个文件(通过点击中间的链接)。第二个总是在第一个完成后开始。管道是罪魁祸首,而不是我最初认为的代码。谢谢。这是一个我几乎一无所知的领域。为什么这会影响第二个脚本,而不会影响后续脚本?知道我怎么关掉吗?或者我是否需要发送一个标题来关闭连接(这在一般情况下是不切实际的)?@N.B.-作为旁白,刚刚选中,虽然Firefox确实显示了这个问题,但在我的Firefox配置中,管道未启用。
CREATE TABLE IF NOT EXISTS `sessions` (
  `set_time` int(11) NOT NULL,
  `session_key` char(32) NOT NULL,
  `data` longtext NOT NULL,
  PRIMARY KEY (`session_key`),
  KEY `set_time` (`set_time`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;