遇到PHP Mysql会话问题

时间:2016-01-02 07:11:45

标签: php html mysql apache session

最近,我的会话和相应的会话变量出现了问题。

问题是,当我发布sessions1.php时,会话变量似乎有效,并被转移到sessions2.php中。

但是,当点击转到sessions3.php的链接时,在sessions3.php中似乎没有设置会话变量。因此,在“if / else”条件内从“else”块返回代码。

当我使用数据库或/ tmp文件设置来存储数据时,似乎发生了类似的事情。

在数据库示例中,会话将写入会话表。但是,当我单击链接时,从sessions2.php开始,这会将我带到sessions3.php,似乎没有设置会话变量。而且,当我点击sessions3.php中的“注销”按钮时,链接会将我带回sessions1.php,这应该是应该发生的事情。但是,当我检查数据库(或至少刷新会话表)时,根据SessionHandler类应该发生的事情,会话不会被删除或销毁。

此外,仍然使用数据库示例:当我提交sessions1.php并将其带到sessions2.php时,会话表中会创建正确的会话行。但是,当我单击指向sessions3.php的链接时,会话表中会创建另一行:这次,数据列中没有任何数据。

另一方面,在没有数据库的测试中,使用文件系统代替:在提交sessions1.php之后,文件出现在/ tmp目录中。但是,在检查时,该文件仍为空。请记住,当使用简单的文件系统示例,“SessionHandler”和数据库连接时,代码不存在于文件中。

任何可能的解决方案?。

我使用的是PHP7,Apache 2.4和MySQL 5.6.27。而且,我想知道我的配置设置(php.ini和/或httpd)是否可能与问题有关(因为,即使没有数据库,sessions2.php和sessions3.php之间的交互也会产生类似的结果(当我到达sessions3.php时,会话变量未设置))。

代码:

sessions1.php(下面)

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Session Test</title>
</head>
<body>
<form method="post" action="sessions2.php">
    <p>
        <label for="name">Enter your first name: </label>
        <input type="text" name="name" id="name">
    </p>
    <p>
        <input type="submit" name="submit" value="Submit">
    </p>
</form>
</body>
</html>


session2.php (below)


<?php

use SomeNamespace\Sessions\SessionHandler;

require_once('/databases/dbConnect.php'); 

require_once('/classes/Sessions/SessionHandler.php');

$handler    =    new SessionHandler($db);
session_set_save_handler($handler);

session_start();

if (isset($_POST['name'])) {
    if (!empty($_POST['name'])) {
        $_SESSION['name'] = htmlentities($_POST['name']);
    } else {
        $_SESSION['name'] = 'Nobody Here!';
    }
}

?>
<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Session Test</title>
</head>
<body>
<p>Hello, <?php
if (isset($_SESSION['name'])) {
    echo $_SESSION['name'];
} else {
    echo 'stranger';
}
    ?>.</p>
<p><a href="sessions3.php">Go to page 3</a></p>
</body>
</html>



session3.php (below)



<?php

use SomeNamespace\Sessions\SessionHandler;

require_once('/databases/dbConnect.php'); 

require_once('/classes/Sessions/SessionHandler.php');

$handler    =    new SessionHandler($db);
session_set_save_handler($handler);

session_start();

if (isset($_POST['logout'])) {
    $_SESSION = [];
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 86400, $params['path'],
        $params['domain'], $params['secure'], $params['httponly']);
    session_destroy();
    header('Location: sessions1.php');
    exit;
}

?>
<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Session Test</title>
</head>
<body>
<p>Hello<?php
if (isset($_SESSION['name'])) {
    echo ' again, ' . $_SESSION['name'];
} else {
    echo ', Nobody!';
}
    ?>.</p>
<form method="post" action="<?= $_SERVER['PHP_SELF']; ?>">
    <p><input type="submit" name="logout" value="Log Out"></p>
</form>
</body>
</html>



SessionHandler.php (below) The session handler class.



namespace SomeNamespace\Sessions;

class SessionHandler implements \SessionHandlerInterface
{

    protected $db;

    protected $useTransactions;

    protected $expiry;

    protected $table_sess = 'sessions';

    protected $col_sid = 'sessionID';

    protected $col_expiry = 'expiry';

    protected $col_data = 'data';

    protected $unlockStatements = [];

    protected $collectGarbage = false;

    public function __construct(\PDO $db, $useTransactions = true)
    {
        $this->db = $db;
        if ($this->db->getAttribute(\PDO::ATTR_ERRMODE) !== \PDO::ERRMODE_EXCEPTION) {
            $this->db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
        }
        $this->useTransactions = $useTransactions;
        $this->expiry = time() + (int) ini_get('session.gc_maxlifetime');
    }

    public function open($save_path, $name)
    {
        return true;
    }

    public function read($session_id)
    {
            try {
        if ($this->useTransactions) {

            $this->db->exec('SET TRANSACTION ISOLATION LEVEL READ        COMMITTED');
            $this->db->beginTransaction();
        } else {
            $this->unlockStatements[] = $this->getLock($session_id); 
        }
        $sql = "SELECT $this->col_expiry, $this->col_data
                FROM $this->table_sess WHERE $this->col_sid = :sessionID";

        if ($this->useTransactions) {
            $sql .= ' FOR UPDATE';
        }
        $selectStmt = $this->db->prepare($sql);
        $selectStmt->bindParam(':sessionID', $session_id);
        $selectStmt->execute();
        $results = $selectStmt->fetch(\PDO::FETCH_ASSOC);
        if ($results) {
            if ($results[$this->col_expiry] < time()) {

                return '';
            }
            return $results[$this->col_data];
        }

        if ($this->useTransactions) {
            $this->initializeRecord($selectStmt);
        }

        return '';
        } catch (\PDOException $e) {
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            throw $e;
        }
    }

    public function write($session_id, $data)
    {
        try {
            $sql = "INSERT INTO $this->table_sess ($this->col_sid,
                    $this->col_expiry, $this->col_data)
                    VALUES (:sessionID, :expiry, :data)
                    ON DUPLICATE KEY UPDATE
                    $this->col_expiry = :expiry,
                    $this->col_data = :data";
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':expiry', $this->expiry, \PDO::PARAM_INT);
            $stmt->bindParam(':data', $data);
            $stmt->bindParam(':sessionID', $session_id);
            $stmt->execute();
            return true;
        } catch (\PDOException $e) {
            if ($this->db->inTransaction()) {
                $this->db->rollback();
            }
            throw $e;
        }
    }

    public function close()
    {
        if ($this->db->inTransaction()) {
            $this->db->commit();
        } elseif ($this->unlockStatements) {
            while ($unlockStmt = array_shift($this->unlockStatements)) {
                $unlockStmt->execute();
            }
        }
        if ($this->collectGarbage) {
            $sql = "DELETE FROM $this->table_sess WHERE $this->col_expiry < :time";
            $stmt = $this->db->prepare($sql);
            $stmt->bindValue(':time', time(), \PDO::PARAM_INT);
            $stmt->execute();
            $this->collectGarbage = false;
        }
        return true;
    }

    public function destroy($session_id)
    {
        $sql = "DELETE FROM $this->table_sess WHERE $this->col_sid = :sessionID";
        try {
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':sessionID', $session_id);
            $stmt->execute();
        } catch (\PDOException $e) {
            if ($this->db->inTransaction()) {
                $this->db->rollBack();
            }
            throw $e;
        }
        return true;
    }

    public function gc($maxlifetime)
    {
        $this->collectGarbage    =    true; 

        return true;
    }

    protected function getLock($session_id)
    {
        $stmt = $this->db->prepare('SELECT GET_LOCK(:key, 50)');
        $stmt->bindValue(':key', $session_id);
        $stmt->execute();

        $releaseStmt = $this->db->prepare('DO RELEASE_LOCK(:key)');
        $releaseStmt->bindValue(':key', $session_id);

        return $releaseStmt;
    }

    protected function initializeRecord(\PDOStatement $selectStmt)
    {
        try {
            $sql = "INSERT INTO $this->table_sess ($this->col_sid, $this->col_expiry, $this->col_data)
                    VALUES (:sessionID, :expiry, :data)";
            $insertStmt = $this->db->prepare($sql);
            $insertStmt->bindParam(':sessionID', $session_id);
            $insertStmt->bindParam(':expiry', $this->expiry, \PDO::PARAM_INT);
            $insertStmt->bindValue(':data', '');
            $insertStmt->execute();
            return '';
        } catch (\PDOException $e) {

            if (0 === strpos($e->getCode(), '23')) {

                $selectStmt->execute();
                $results = $selectStmt->fetch(\PDO::FETCH_ASSOC);
                if ($results) {
                    return $results[$this->col_data];
                }
                return '';
            }

            if ($this->db->inTransaction()) {
                $this->db->rollback();
            }
            throw $e;
        }
    }

}

0 个答案:

没有答案