0

私はコードをもっている:

class db {
    var $connection;
    function escape($esc) {
        return str_replace(array('%','_'),array('\%','\_'),mysqli_real_escape_string($this->connection,$esc));
    }
[...]
}
$db=new db;



class Session {
    private function read($sid) {
        global $db;
        $r=$db->query('SELECT `data` FROM `sess` WHERE `hash`=\''.$db->escape($sid).'\' LIMIT 1');
        if ($this->debug) echo 'Read: <u>SELECT `data` FROM `sess` WHERE `hash`=\''.$db->escape($sid).'\' LIMIT 1</u><br/>';
        if($db->num_rows($r)==1) {
            $fields=$db->fetch_assoc($r);
            return $fields['data'];
        }
        else return '';
    }

    private function write($sid, $data) {
        global $db;
        if ($this->debug) echo 'Write: <u>REPLACE INTO `sess`(`hash`,`data`) VALUES(\''.$db->escape($sid).'\',\''.$db->escape($data).'\')</u><br/>';
        $db->query('REPLACE INTO `sess`(`hash`,`data`) VALUES(\''.$db->escape($sid).'\',\''.$db->escape($data).'\')');
        return $db->connection->affected_rows;
    }
[...]
function __construct($debug=false) {
    session_set_save_handler(
        array(&$this, 'open'),
        array(&$this, 'close'),
        array(&$this, 'read'),
        array(&$this, 'write'),
        array(&$this, 'destroy'),
        array(&$this, 'clean')
    );
    $this->debug=$debug;
    session_start();
}
}
$sessions=new Session(true);

そして、私は取得し続けますFatal error: Call to a member function escape() on a non-object on line 61(の2行目function write($sid, $data))。奇妙なことに、デバッガーは関数readが正常に実行されたことを示しています。なぜこれが起こっているのか、誰かに光を当ててもらえますか?

4

1 に答える 1

2

ほとんどの場合(メソッドを呼び出す場所はわかりませんが)、$db変数が宣言される前のどこかで呼び出されます。

正しい解決策は、コンストラクターを介して変数をクラスに注入することです。

public function __construct(db $db, $debug = false) {
    $this->db = $db;
    ....
}

次に、$this->db必要な場所で使用します。

グローバル変数を使用する際の問題は、デクレレーションの順序が重要であるということです。つまり、$db呼び出す前に宣言する必要がありますが、そうする必要があるかどうかは明らかではありません。。コンストラクターを実行するにはオブジェクトが必要なので、これは明らかです。Session::write()$db

なぜグローバルステートはとても邪悪なのですか?

于 2012-07-15T16:17:31.610 に答える