How should you include a Database class in other classes?

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
...
}
 
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.
 
Last edited:
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
...
}

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
 
Back
Top