Question

I was having some issues building a singleton class for a mysqli object to be used by more than one class. I originally got the error Access to undeclared static property: database::$DBH which I don't understand as the property is not static. I presumed it might of been because phpversion() returned 5.2.17 and I discovered the singleton pattern could only be done using version >5.3? (Could be completely wrong). I looked into it and found that my server provider, allows me to chose the version of PHP that I can use. I've currently selected 5.3.3 but again, same error. Either I've got to wait for the server to 'refresh' it's settings. Or I do have a legitimate error with the version 5.3.3

class database{
    private$DBH;
    private static$singleton;
    protected function __construct(){
        $this->$DBH=new mysqli(HOST,USER,PASSWORD,DATABASE);
        //also tried self::$DBH;
        //if(mysqli_connect_errno())print_r(mysqli_connect_error());
    }
    public static function instance(){
        if(!(self::$singleton instanceof self))self::$singleton=new self();
        return self::$singleton;
    }
    public static function get(){
        return self::instance()->$DBH;
    }
    private function __wake(){}
    private function __clone(){}
}
class test{
    public function __construct(){
        $get=database::get()->prepare('SELECT column FROM table');
        $get->execute();
        $get->bind_result($col);
        while($get->fetch()){
            print($col."\n");
        }
        //$get->close(); not required.
    }
}
$t=new test();

IS there any alternatives to want I'm trying to achieve? (singular mysqli object to be used with multiple classes, also what a 'securer' method from a standard object.)

Should I extend my database class with mysqli?

Should I just use PDO?

OR again better still! Get a better server provider where their services are up to date.

Was it helpful?

Solution

Do not make it overcomplicated, just extend MySQLi class, add some methods to it. MySQLi is already a connector itself, why store another connector inside a connector?

class Database extends MySQLi {
     private static $instance = null ;

     private function __construct($host, $user, $password, $database){ 
         parent::__construct($host, $user, $password, $database);
     }

     public static function getInstance(){
         if (self::$instance == null){
             self::$instance = new self(HOST, USER, PASSWORD, DATABASE);
         }
         return self::$instance ;
     }
}

$db = Database::getInstance();
$result = $db->query("SELECT 1 FROM table");

A few tips:

  • Non-static properties are accessed via $object->property

  • Static properties are accessed via: self::$property or Database::$property or static::$property

  • use of PDO is really good since you can bind values, thus securing your database from injections. As an option - extend PDO class.

OTHER TIPS

You need to remove the $ from $DBH in $this->$DBH=new mysqli and in return self::instance()->$DBH; since you're already referring to its current object with $this->DBH

class database{
    private $DBH;
    private static $singleton;
    protected function __construct(){
        $this->DBH=new mysqli(HOST,USER,PASSWORD,DATABASE);
        //also tried self::$DBH;
        //if(mysqli_connect_errno())print_r(mysqli_connect_error());
    }
    public static function instance(){
        if(!(self::$singleton instanceof self)) self::$singleton=new self();
        return self::$singleton;
    }
    public static function get(){
        return self::instance()->DBH;
    }
    private function __wake(){}
    private function __clone(){}
}
class test{
    public function __construct(){
        $get=database::get()->prepare('SELECT column FROM table');
        $get->execute();
        $get->bind_result($col);
        while($get->fetch()){
            print($col."\n");
        }
        //$get->close(); not required.
    }
}
$t=new test();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top