It seems (at least to me) very natural to concentrate all database credentials and what-not in a Database class (singleton), that provides a single database access point to other classes. The Database object is a static object independent on instances. What I find frustrating is that PHP static variable cannot reference an object, so I wonder how should it be included? Making it an instance variable can work but I find it strange as it is apparently static. Even it's singleton, I find making a static variable instance variable uncomfortable. How should it be done? What's wrong with my below approach? How I am using it now which I find unnatural. Code: <?php //Database class require_once "config.php"; //load database credentials from config file final class MySQL { private static $mysql = null; //single instance private $dsn; //data source name private $dbh; //database handle private function __construct() { try { $this->dsn = "mysql:host=". DB_HOST .";dbname=". DB_NAME .";port=". DB_PORT; $this->dbh = new PDO($this->dsn, DB_USER, DB_PASSWORD); } catch (PDOException $ex) { exit("Database connection failed: " . $ex->getMessage()); } } public static function getInstance() { if (self::$mysql == null) { self::$mysql = new MySQL(); } return self::$mysql; } //key function to provide access to DB public function request(string $query, array $params=null): array { ... } Code: <?php //a class that needs database access class Bookstore { protected $address; protected $owner; static protected $mysql = new MySQL(); //seems natural but not possible protected $mysql; //so instance instead, but unnatural public function __construct() { $this->mysql = MySQL::getInstance(); //assigning a Database obj to each instance ... } public function getAllBooks() { $books = $this->mysql->request($someQuery, $someParams); //accessing DB ... }
Unless you're getting ready for the classic singleton interview question, put the fancypants code away. Keep it simple, and put them into an array in a secure config file.
Sorry I don't know this language, but in my experience the only reason you might need a singleton is if you want to restrict the number of connections to the database so there's only a single one. If you don't need to do that, then it's probably creating hassle for yourself as @kmiklas says. GAT
singleton is fine for this but might not help because usually database libs already have builtin connection pools, timeouts, ... you're assigning the same Database obj to each instance which is what you want. $this->mysql = MySQL::getInstance(); //assigning a Database obj to each instance