php singleton database connection, is this code ba

2020-02-01 08:57发布

问题:

I'm trying to create a simple to use singleton class to connect to mysql database and do queries, the code works fine and i haven't had any problems with it, but since I'm new to OOP I'm wondering whether this is bad practice or not.

Here's the class

class Database {
private $databaseName = 'dbname';
private $host = 'localhost';
private $user = 'user';
private $password = 'pass'; 
private static $instance; //store the single instance of the database

private function __construct(){
    //This will load only once regardless of how many times the class is called
    $connection = mysql_connect($this->host, $this->user, $this->password) or die (mysql_error());
    $db = mysql_select_db($this->databaseName, $connection) or die(mysql_error()); 
    echo 'DB initiated<br>';
}

//this function makes sure there's only 1 instance of the Database class
public static function getInstance(){
    if(!self::$instance){
        self::$instance = new Database();
    }
    return self::$instance;     
}

public function connect() { 
    //db connection
} 
public function query($query) {
    //queries   
    $sql = mysql_query($query) or die(mysql_error()); 
    return $sql;
}

public function numrows($query) {
    //count number of rows  
    $sql = $this->query($query);
    return mysql_num_rows($sql);
}


}

//Intantiate the class
$database = Database::getInstance();

and when i want to use the class I would do:

$query = "SELECT * FROM registrations";
echo $database->numrows($query);
$sql = $database->query($query);

回答1:

Singletons are bad news.

  • They introduce global state into a program. Most programmers should be familiar with why global state is bad.
  • They introduce tight coupling between the singleton and any class that uses it. This means you can't reuse the classes in question without reusing the singleton too.
  • They make unit testing of classes that depend on the singleton problematic because you can't easily replace the singleton with a mock.
  • They encourage a coding style where classes attempt to resolve their own dependencies. This is bad because it can reduce clarity regarding what dependencies the class has.
  • PHP has a Share Nothing Architecture, meaning that PHP singletons aren't really singletons at all, there can be multiple instances alive at any one time (one per open request).
  • What happens if you suddenly discover at some later date that you actually need more than one of the resource that's being provided by the singleton? It's a more common scenario than you might think

You're better off looking at dependency-injection instead, as it resolves the above issues.



回答2:

I think a singleton can be OK for a connection manager, but not for a connexion itself.

You never know when you'll need to have an extra connection for a specific part of your development. Let say you suddently need to add a synchronisation with a remote database.

A connection manager (who can manage multiple connection) can be a singleton. A connection itself; no.

You connection manager should also be able to load "Drivers", so that you'll be able to instanciate a MySQL connection and the day you need msSQL, sqLite or anything else, you're able to add the needed drivers.



回答3:

This pattern will be fine because the singleton will only apply to the current user session. The decision really comes down to what your priority is. If you want faster performance for the user then you want to allow more database connections per user, but if you want to limit how hard your database gets hit then the singleton gives you a good middle of the road.



回答4:

The only positive argument I've heard for the Singleton design pattern in PHP was from a developer who implemented a Singleton database connection in conjunction with a Memcached object. I didn't actually get a chance to look at the code and performance but he was able to put forward a coherent argument.

Personally I don't believe that the Singleton design pattern is very relevant to PHP, which is largely stateless anyway (as pointed out before each request will have a singleton).