Singleton class for database mysqli phpversion 5.2

2019-04-16 15:12发布

问题:

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.

回答1:

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.


回答2:

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();