致命错误:在非对象(MySQL/Sessions)上调用成员函数prepare()


Fatal error: Call to a member function prepare() on a non-object (MySQL/Sessions)

我知道这是一个常见的问题,但我已经了解了很多其他答案,无法理解为什么这仍然失败。所以,我很抱歉,但希望有人能指出哪里出了问题!

index.php中,执行以下代码:

// Set Database Configuration
$dbconfig = array( 
    'host' => getenv('MYSQL_DB_HOST'),
    'user' => getenv('MYSQL_USERNAME'), 
    'pass' => getenv('MYSQL_PASSWORD'), 
    'name' => getenv('MYSQL_DB_NAME') 
); 
// Start database sessions
$db = oadb::getInstance();
$db->show_errors();
echo $db->prepare("hello");
// Open a new session
$sess = new oasession();
session_start();

getInstance()$db->prepare()发生时没有任何问题,并且会回显"hello"文本以确认这一点。

当调用new oasession()时,轮子开始脱落。oasessions()数是一个会话处理程序,它接管PHPs的正常会话处理,并将其放入MySQL数据库中。

sessions.inc.php包含如下类(我删除了一些不相关的函数):

class oasession {
   var $life_time;
   function oasession() {
      // Read the maxlifetime setting from PHP
      $this->life_time = get_cfg_var("session.gc_maxlifetime");
      // Register this object as the session handler
      session_set_save_handler( 
        array( &$this, "open" ), 
        array( &$this, "close" ),
        array( &$this, "read" ),
        array( &$this, "write"),
        array( &$this, "destroy"),
        array( &$this, "gc" )
      );
   }
   function open( $save_path, $session_name ) {
        global $sess_save_path;
        $sess_save_path = $save_path;
        // Don't need to do anything. Just return TRUE.
        return true;
   }
   function read( $id ) {
       global $db;
           // Set empty result
           $data = '';
           // Fetch session data from the selected database
           $time = time();
           $newid = $db->prepare($id);
           $sql = "SELECT `session_data` FROM `OA-Auth_sessions` WHERE `session_id` = '$newid' AND `expires` > $time";
           $rs = $db->query($sql);                           
           $a = $db->num_rows($rs);
           if($a > 0) {
             $row = $db->fetch_array($rs);
             $data = $row['session_data'];
           }
           return $data;
        }
    function write( $id, $data ) {
        global $db;
         // Build query                
         $time = time() + $this->life_time;
         $newid = $db->prepare($id);
         $newdata = $db->prepare($data);
         $sql = "REPLACE `OA-Auth_sessions` (`session_id`,`session_data`,`expires`) VALUES('$newid', '$newdata', $time)";
         $rs = $db->query($sql);
         return TRUE;
      }
}

它可以毫无问题地使用read($id)函数,但当它尝试使用write($id,$data)函数时,它失败了,并出现以下错误。。。

Fatal error: Call to a member function prepare() on a non-object in sessions.class.php on line 66

这表明从$db->prepare()执行的prepare函数不是一个有效的对象。

我试着通过在新的oasession()之前和之后放置print_r()来测试这一点,并且两者都打印了对象描述,在新的oa()调用之前或之后运行其他$db->prepare()调用没有问题。

你有没有想过是什么原因导致了这次事故?

非常感谢!

根据php.net:设法解决了这个问题

当使用对象作为会话保存处理程序时,重要的是用PHP注册关闭函数以避免意外PHP在关闭时内部销毁对象的方式产生的副作用并且可以防止写入和关闭被调用。通常情况下应使用register_shutdown_function()函数。

正在将以下内容添加到sessions.class.php oasession()函数中。。。

register_shutdown_function('session_write_close');

修复了这一切:)