PHP PDO Singleton usage in other classes

Markshall

Русский Стандарт
Contributor
Dec 18, 2010
2,638
2,393
Right, basically I've got an MySQLi singleton wrapper which I want to use in other classes.

It is as follows:

PHP:
<?php
class Database extends PDO {
    public static $instance;
    private $connection;
   
    public function __construct() {
        $this->connection = parent::__construct('mysql:host=localhost;dbname=lol', 'lol', 'lol');
    }
   
    public static function getInstance() {
        if (!isset(self::$instance)) {
            self::$instance = new self();
        }
       
        return self::$instance;
    }
}

So, rather than doing
PHP:
$query = $db->prepare("SELECT......");
...and opening a new connection to the database each time, I do
PHP:
$query = $db::getInstance()->prepare("SELECT.......");
...which will check if a connection has already been established and just return it. Easier on the database

Now, I want to use this in other classes, for example:

PHP:
<?php
class Core {
    private $_db;
   
    public function __construct(Database $db) {
        if (!$db || $db->connect_errno > 0) {
            die ('MySQLi connection error. Error sent from class.core.php');
        } else {
            $this->_db = $db;
        }
    }
   
   
    public function AddLog($User, $Event) {
        $log = $this->_db->prepare("INSERT INTO `Logs` (`UserID`, `Event`, `TimeStamp`, `IPAddress`) VALUES (?, ?, ?, ?);");
        if ($log->execute([$User, $Event, time(), $_SERVER['REMOTE_ADDR']])) {
            return true;
        }
       
        return false;
    }
   
}

...but this does not allow me to to use my getInstance() method, how would I go about being able to do this?

Thanks,
Mark
 

RastaLulz

fight teh power
Staff member
May 3, 2010
3,934
3,932
In your example, you're using PDO, not MySQLi. Could you also show an example of how you're trying to call your static method in your Core class?
 
Last edited:

Markshall

Русский Стандарт
Contributor
Dec 18, 2010
2,638
2,393
In your example, you're using PDO, not MySQLi. Could you also show an example of how you're trying to call your static method in your Core class?
Whoops lel

Also, here is an example of how I've been trying to do a query in my Core class

PHP:
$query = $this->_db::getInstance()->prepare("SELECT....");
 

Markshall

Русский Стандарт
Contributor
Dec 18, 2010
2,638
2,393
You're referring to an instance of the class, not the connection?
I just want to be able to do the whole getInstance() thing within the class. It throws an error. When I'm at my computer, I shall post the description of the error.

In class.core.php, I tried doing private static $_db; but that never worked
 
Last edited:

BIOS

ಠ‿ಠ
Apr 25, 2012
906
247
I just want to be able to do the whole getInstance() thing within the class. It throws an error. When I'm at my computer, I shall post the description of the error.

In class.core.php, I tried doing private static $_db; but that never worked

Do you mean like this?

PHP:
<?php
class Database {
    public static $instance;
    private $connection;
 
    public function __construct() {

        self::$instance = 'construct';

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

    }
}

class Core {
 
    public function __construct($db) {

        $this->db = $db;

    }
 
 
    public function test() {

        return $this->db->getInstance();
        // do stuff

    }
 
}

$db = new Database();
$core = new Core($db);

echo $core->test();
?>
 

Markshall

Русский Стандарт
Contributor
Dec 18, 2010
2,638
2,393
Do you mean like this?

PHP:
<?php
class Database {
    public static $instance;
    private $connection;

    public function __construct() {

        self::$instance = 'construct';

    }

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

    }
}

class Core {

    public function __construct($db) {

        $this->db = $db;

    }


    public function test() {

        return $this->db->getInstance();
        // do stuff

    }

}

$db = new Database();
$core = new Core($db);

echo $core->test();
?>
Yes, like that. But it's a static method so it'd have to be called as such:

PHP:
return $this->_db::getInstance();

I'm not sure how to get around that.
 

BIOS

ಠ‿ಠ
Apr 25, 2012
906
247
Yes, like that. But it's a static method so it'd have to be called as such:

PHP:
return $this->_db::getInstance();

I'm not sure how to get around that.
The above example uses a static method too for Database::getInstance() and returns self::$instance of the Database constructor which is currently printed, however would probably be replaced with the PDO connection.

e.g.
PHP:
    public function __construct($host, $dbname, $user, $pswd) {

        self::$instance = new PDO('mysql:host='.$host.';dbname='.$dbname.'', $user, $pswd);

    }

$db = new Database('localhost', 'lol', 'lol', 'lol');
 
Last edited:

RastaLulz

fight teh power
Staff member
May 3, 2010
3,934
3,932
Yes, like that. But it's a static method so it'd have to be called as such:

PHP:
return $this->_db::getInstance();

I'm not sure how to get around that.
That gives you an instance of the Database class, not an instance of the PDO connection that you've set to $connection, which is what you'd use the prepare method on.
 

Weasel

👄 I'd intercept me
Nov 25, 2011
4,135
2,461
As far as I can see, guessing without the actual error, it's unable to find the Database class because the file isn't included.

Also, a very minor improvement:
PHP:
public function AddLog($User, $Event) {
        $log = $this->_db->prepare("INSERT INTO `Logs` (`UserID`, `Event`, `TimeStamp`, `IPAddress`) VALUES (?, ?, ?, ?);");
        if ($log->execute([$User, $Event, time(), $_SERVER['REMOTE_ADDR']])) {
            return true;
        }
   
        return false;
    }
The above can be simplified into the following, as PDOStatement::execute ($log->execute) returns either true of false;
PHP:
public function AddLog($User, $Event) {
        $log = $this->_db->prepare("INSERT INTO `Logs` (`UserID`, `Event`, `TimeStamp`, `IPAddress`) VALUES (?, ?, ?, ?);");
   
        return $log->execute([$User, $Event, time(), $_SERVER['REMOTE_ADDR']];
    }
 

BIOS

ಠ‿ಠ
Apr 25, 2012
906
247
Yes, like that. But it's a static method so it'd have to be called as such:

PHP:
return $this->_db::getInstance();

I'm not sure how to get around that.
You could create functions within the database class to handle all types of data, e.g. query/numrows/fetch functions, that way it would still remain very flexible & less logic would be needed in the other classes as the database logic would be more maintained by the class.

Here's how my database class works (in a similar way):
PHP:
        public function initiate(){
         
            if($this->db instanceof PDO){
                return $this->db;
            }

        }

        public function rows($query, $bind = []){

            try{
             
                $this->stmt = $this->db->prepare($query);
                $this->stmt->execute($bind);
             
                $this->result = $this->stmt->rowCount();
                return $this->result;
             
            }catch(PDOException $e){

                $this->logger->addWarning("SQL error: ".$e);
                exit('Sorry, something happened. Please try again.');

            }

        }
 
Last edited:

Users who are viewing this thread

Top