dongzen7263 2012-11-20 14:27
浏览 71
已采纳

PHP Session Handler不写入数据库

I need help with the class below - its not writing to the database and I have no idea why. I know the "read" method is called, but not the "write" method :S

This is the code I'm using:

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);

and this is the class ...

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());
        }
    }

}

Hope you guys can help :)

Thanks, Gem

  • 写回答

1条回答 默认 最新

  • dongyata3336 2012-11-20 14:36
    关注

    One, you don't need to pass by reference. Do this instead:

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

    To test if the save/write is working, you could try this:

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

    This should trigger a write to the session store and flush anything to be written. In this case it should display WRITING- Foo if your write method is being called.

    If the DB is not being written, but the method is being called, there are other issues.

    The first thing I'd look at is the :tableName you're replacing in the prepared statement. You cannot prepare-replace column names or tables. Change your statement to this:

     $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
            ");
    

    If you do substitue in variables for table names or columns, make sure you whitelist them before using to be safe against opening an injection hole.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 fluent的在模拟压强时使用希望得到一些建议
  • ¥15 STM32驱动继电器
  • ¥15 Windows server update services
  • ¥15 关于#c语言#的问题:我现在在做一个墨水屏设计,2.9英寸的小屏怎么换4.2英寸大屏
  • ¥15 模糊pid与pid仿真结果几乎一样
  • ¥15 java的GUI的运用
  • ¥15 Web.config连不上数据库
  • ¥15 我想付费需要AKM公司DSP开发资料及相关开发。
  • ¥15 怎么配置广告联盟瀑布流
  • ¥15 Rstudio 保存代码闪退