3
votes

I have done quite a fair amount of research, troubleshooting, and searching in an attempt to solve my problem, with no luck. So here is the error...

Call to a member function prepare() on a non-object

The code generating this error is in my user Auth class as follows...

$this->dbManager->db->prepare('INSERT INTO users (email, password, user_salt, is_admin) VALUES (:email, :password, :user_salt, :is_admin)');

dbManager comes from $db which I have passed into the __construct of my class as follows...

public function __construct($db) {
        $this->siteKey = 'notImportant';
        $this->dbManager = $db;
    }

$db originates from my sql class, which I require in one "bootstrap" php file that the index.php requires.

The bootstrap.php code is as follows...

<?php

// Load firePHP library
//require_once('FirePHPCore/FirePHP.class.php');
ob_start();
//$firephp = FirePHP::getInstance(true);

// Load all the classes/libs...
require_once 'classes/sql.class.php';

require_once 'classes/auth.class.php';
$db = sql::getInstance();
session_start();
$auth = new Auth($db);

require_once 'lib/handlepost.php';

And finally, my code for sql.class.php is as follows...

class sql {
    public static $db = false;
    private $database_host = '';
    private $database_user = '';
    private $database_pass = '';
    private $database_db = '';

    private function __construct() {
        if (self::$db === false) {
            $this -> connect();
        }
        return self::$db;
    }


    public static function getInstance() {
        if (!self::$db) {
            self::$db = new sql();
        }

        return self::$db;
    } 


    private function connect() {
        $dsn = $this -> database_type . ":dbname=" . $this -> database_db . ";host=" . $this -> database_host;
        try {
            self::$db = new PDO($dsn, $this -> database_user, $this -> database_pass, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''));
            self::$db -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch (PDOException $e) {
            //print_r($e->errorInfo);
            //echo 'Connection failed: ' . $e->getMessage();
        }
    } // End Connect

}

I am new to using PDO, which is causing me some confusion to begin with...

Any help getting this to work with an explanation of what I am doing wrong would be extremely appreciated.

1

1 Answers

4
votes

The error you're seeing means that $this->dbManager->db is not an object. Thus trying to call a method on it (prepare) gives you an error.

Edit: Sorry, I see your error now.

Sql::$db is a static member, but you're accessing it as if it was a property. You can't do that. I suggest changing the static member on your class sql to a regular property. E.g.: remove static from public static $db = false;. Replace all self::$db with $this->db and rewrite the getInstance method to:

public static function getInstance() {
  if (!self::$instance) {
    self::$instance = new self();
  }
  return self::$instance;
}

So basically, your error has nothing specifically to do with PDO, but rather with static vs. member properties.

You could try to skip the Sql class all together:

class ConnectionManager {
  private static $db = false;
  private static $database_host = '';
  private static $database_user = '';
  private static $database_pass = '';
  private static $database_db = '';

  public static function getConnection() {
    if (!self::$db) {
      self::connect();
    }
    return self::$db;
  } 

  private static function connect() {
    $dsn = self::database_type . ":dbname=" . self::database_db . ";host=" . self::database_host;
    try {
      self::$db = new PDO($dsn, self::database_user, self::database_pass, array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''));
      self::$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    } catch (PDOException $e) {
      //print_r($e->errorInfo);
      //echo 'Connection failed: ' . $e->getMessage();
    }
  }
}

...

class Auth {
  public function __construct($db) {
    $this->siteKey = 'notImportant';
    $this->db = $db;
  }

  public function foo() {
    $stmt = $this->db->prepare('INSERT INTO users (email, password, user_salt, is_admin) VALUES (:email, :password, :user_salt, :is_admin)');
    $stmt->execute(...);
  }
}

...

$db = ConnectionManager::getConnection();
session_start();
$auth = new Auth($db); // <- Here $db is an actual instance of PDO