一个不寻常的“;调用非对象上的成员函数”;


An unusual case of "Call to a member function on a non-object"

我有一个代码:

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 61function write($sid, $data)的第二行)。奇怪的是,调试器显示函数read已经成功执行。有人能解释一下为什么会发生这种情况吗?

很可能(尽管我们没有看到在哪里调用该方法),它是在声明$db变量之前的某个地方调用的。

正确的解决方案是通过构造函数将变量注入类。

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

然后在任何需要的地方使用$this->db

使用全局变量的问题是,分离的顺序很重要,这意味着在调用Session::write()之前必须声明$db,但不明显需要这样做。现在,这是显而易见的,因为您需要一个$db对象才能运行您的构造函数!

为什么全球国家如此邪恶