1

我需要以下课程的帮助 - 它没有写入数据库,我不知道为什么。我知道调用了“读取”方法,但没有调用“写入”方法:S

这是我正在使用的代码:

require '../application/database.php';
$db = new Database('localhost', 'root', '', 'gemgale');

require '../application/session.php';
$session = new Session($db);

session_set_save_handler(
    array(&$session, 'open'),
    array(&$session, 'close'),
    array(&$session, 'read'),
    array(&$session, 'write'),
    array(&$session, 'destroy'),
    array(&$session, 'clean')
);
session_start();
var_dump($session);
$_SESSION['something'] = "gem";
var_dump($_SESSION);
#$session->delete();
#var_dump($_SESSION);

这就是课堂......

class Session
{
    ###########################################################################
    private $expiry = 3600;
    private $securityCode = "gnvriev847e8grdinvrdg5e8g4r7fr7rdvreh8^£*^£FGgyhf";
    private $tableName = "session_data";
    ###########################################################################
    private $dbh;

    function __construct(Database $db)
    {
        $this->dbh = $db->getConnection();

        ini_set('session.cookie_lifetime', 0);
        ini_set('session.gc_maxlifetime', $this->expiry);
    }

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

    function close()
    {
        return true;
    }

    function read($session_id)
    {
        echo $session_id;
        print "READING";
        $time = time();
        $hua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
        $hua = $hua . $this->securityCode;
        $hua = md5($hua);
        try {
            $stmt = $this->dbh->prepare("
            SELECT session_data
            FROM :tableName
            WHERE session_id = :sesID
              AND session_expire > :time
              AND http_user_agent = :hua
            LIMIT 1
        ");
            $stmt->bindParam("tableName", $this->tableName);
            $stmt->bindParam("sesID", $session_id);
            $stmt->bindParam("time", $time);
            $stmt->bindParam("hua", $hua);
            $stmt->execute();
        } catch (PDOException $e) {
            echo $e->getMessage();
            return false;
        }
        $rs = $stmt->fetch();
        if (!$rs)
            return '';
        else
            return $rs['session_data'];

    }

    function write($session_id, $session_data)
    {
        print "WRITING";
        $expiry = time() + $this->expiry;
        $hua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
        $hua = $hua . $this->securityCode;
        $hua = md5($hua);
        try {
            $stmt = $this->dbh->prepare("
                INSERT INTO :tableName (
                  session_id,
                  http_user_agent,
                  session_data,
                  session_expiry
                )
                VALUES (
                  :sessID,
                  :hua,
                  :sdata,
                  :expiry
                )
                ON DUPLICATE KEY UPDATE
                  session_data = :sdata,
                  session_expire = :expiry
            ");

            $stmt->bindParam("tableName", $this->tableName);
            $stmt->bindParam("sessID", $session_id, PDO::PARAM_STR);
            $stmt->bindParam("hua", $hua);
            $stmt->bindParam("sdata", $session_data, PDO::PARAM_STR);
            $stmt->bindParam("expiry", $expiry);
            $stmt->execute();
        } catch (PDOException $e) {
            echo $e->getMessage();
            return false;
        }
        if ($stmt->rowCount() > 1)
            return true;
        else
            return '';

    }


    function destroy($session_id)
    {
        try {
            $stmt = $this->dbh->prepare("
                DELETE FROM :tableName
                WHERE session_id = :id
            ");
            $stmt->bindParam("tableName", $this->tableName, PDO::PARAM_STR);
            $stmt->bindParam("id", $session_id, PDO::PARAM_STR);
            $stmt->execute();
        } catch (PDOException $e) {
            echo $e->getMessage();
            return false;
        }
        return true;
    }


    function clean($maxLifeTime)
    {
        try {
            $x = time() - $maxLifeTime;
            $stmt = $this->dbh->prepare("
                DELETE FROM :tableName
                WHERE session_expire < :x
            ");
            $stmt->bindParam("tableName", $this->tableName, PDO::PARAM_STR);
            $stmt->bindParam("x", $x, PDO::PARAM_INT);
            $stmt->execute();
        } catch (PDOException $e) {
            die($e->getMessage());
        }
        return true;
    }

    function delete()
    {
        $oldID = session_id();
        session_regenerate_id();
        $this->destroy($oldID);
        session_unset();
        session_destroy();
    }


    function getActive()
    {
        $this->clean($this->expiry);
        try {
            $stmt = $this->dbh->prepare("
                SELECT COUNT(session_id) as count
                FROM :tableName
            ");
            $stmt->bindParam("tableName", $this->tableName, PDO::PARAM_STR);
            $stmt->execute();
            $rs = $stmt->fetch();
            return $rs['count'];
        } catch (PDOException $e) {
            die($e->getMessage());
        }
    }

}

希望大家能帮忙:)

谢谢,宝石

4

1 回答 1

1

一,你不需要通过引用传递。改为这样做:

session_set_save_handler(
   array($session, 'open'),
   array($session, 'close'),
   array($session, 'read'),
   array($session, 'write'),
   array($session, 'destroy'),
   array($session, 'clean')
);

要测试保存/写入是否有效,您可以尝试以下操作:

session_start();
$_SESSION['something'] = "gem";
session_write_close();
echo "- Foo";

这应该触发对会话存储的写入并刷新要写入的任何内容。在这种情况下,它应该显示WRITING- Foo是否正在调用您的 write 方法。

如果没有写入数据库,但正在调用方法,则还有其他问题。

我首先要看的是您在准备好的语句中替换的 :tableName 。您不能准备替换列名或表。将您的声明更改为:

 $stmt = $this->dbh->prepare("
            INSERT INTO ".$this->tableName."  (
              session_id,
              http_user_agent,
              session_data,
              session_expiry
            )
            VALUES (
              :sessID,
              :hua,
              :sdata,
              :expiry
            )
            ON DUPLICATE KEY UPDATE
              session_data = :sdata,
              session_expire = :expiry
        ");

如果您确实用变量替换表名或列,请确保在使用之前将它们列入白名单,以防止打开注入孔。

于 2012-11-20T14:36:53.703 回答