How should you include a Database class in other classes?

Discussion in 'App Development' started by deanstreet, Sep 7, 2021.

  1. 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
    ...
    }
    
     
  2. kmiklas

    kmiklas

    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: Sep 7, 2021
  3. 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
     
  4. 2rosy

    2rosy

    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