4
\$\begingroup\$

I want to ask whether is good practice to have single instance of database connection or declare new every times when we needed? I have this two designs shown in below:

This is database class:

<?php
class Database extends PDO {
    //Variable declaration
    private $host = "localhost";
    private $passwd = "";
    private $username = "root";
    private $dbname = "";

    //Connect to DB when the class construct
    public function __construct($host=NULL, $dbname=NULL, $username=NULL, $passwd=NULL) {
        if(isset($host) && !empty($host)) {
            $this->host = $host;
        }

        if(isset($dbname) && !empty($dbname)) {
            $this->dbname = $dbname;
        }

        if(isset($username) && !empty($username)) {
            $this->username = $username;
        }

        if(isset($passwd) && !empty($passwd)) {
            $this->passwd = $passwd;
        }

        parent::__construct("mysql:dbname=$this->dbname;host=$this->host", $this->username, $this->passwd, NULL);
        parent::setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        parent::setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    }

}
?>

Method 1: Dependency Injection

<?php
class User {
    private $db;

    public function __construct(Database $db) {
        $this->db = $db;
    }

    //Some update and insert below here
}

class Employee {
    private $db;

    public function __construct(Database $db) {
        $this->db = $db;
    }

    //Some update and insert below here
}
?>

So, I will do this when I want to use the classes:

<?php 
    $db = new Database();

    $user = new User($db);
    $user->update($id,$data);

    $emp = new Employee($db);
    $emp->delete($id);
?>

or the other ways?

Method 2:

<?php
class User {
    private $db;

    public function __construct() {
        $this->db = new Database();
    }

    //Some update and insert below here
}

class Employee {
    private $db;

    public function __construct() {
        $this->db = new Database();
    }

    //Some update and insert below here
}
?>

and when I want to use it I will:

<?php  
    $user = new User();
    $user->update($id,$data);

    $emp = new Employee();
    $emp->delete($id);
?>

Which method is preferable or better? Offer an explanation if possible.

\$\endgroup\$
4
\$\begingroup\$

In this situation, I would say to prefer dependency injection. The reasons being:

  1. You may not only ever run your code against a single database. For example, if your project grows large, you may have separate databases for different regions about the world (North America, Europe, etc). You could also easily have a test database, or a stable-test and an experimental-test, etc., etc. All of this can be controlled by configuration. Of course, you could put this configuration-based logic inside your Database class, but..

  2. You may want different types of databases. Right now you might be using MySQL; later you may use Oracle, or PostgreSQL, or an in-memory database, or a mock database that has no backing store. Using dependency injection lets you very easily switch between these, provided you adhere to the same interface for all of them. You may even start in one region where MySQL is readily available, then expand to another where you can only get Oracle hosts. Changing types is useful for easily changing technologies later, but also because..

  3. Using dependency injection makes it easier to test. You can test against an in-memory database for your unit tests, and against an actual remote database during integration testing.

Of course, dependency injection isn't a cure-all and has its own problems, such as:

  1. Dependency injection is infectious. Somebody somewhere has to know how to construct your object. If your object has its dependencies injected, then it has to know how to construct the dependencies. If it doesn't know that, then the next level up has to know, or the next level from there, or.. etc, etc. The result of this is that..

  2. Your classes become more tightly coupled. Some of your classes become aware of the dependencies of their other classes, by virtue of having to inject their dependencies. A good dependency injection framework can help with this. I don't use PHP much so I'm not aware of any.

This is Code Review, of course, and I'd be remiss if I didn't comment on your code itself:

<?php  
    $user = new User();
    $user->update($id,$data);

    $emp = new Employee();
    $emp->delete($id);
?>

To me (admittedly a non-PHP guy) this is an extremely strange pattern. A User and an Employee would seem to be model classes, but here you have them making database calls - you're mixing concerns for these objects. This is a great situation to use the data access object, or DAO, pattern:

<?php
    class User {
        private $data;

        public function __construct() {
            $data = "some_data";
        }
    }

    interface UserDao {
        public function saveUser(User $user);
    }

    // A DAO implementation which knows how to communicate using
    // PDO objects. Can be injected with a PDO object configured
    // to connect to any host, DBMS, etc.
    class PDOUserDao implements UserDao {
        private $pdo;

        public function __construct(PDO $pdo) {
            $this->pdo = $pdo;
        }

        public function saveUser(User $user) {
            // insert pdo insert/update logic here
        }
    }

    class InMemoryUserDao implements UserDao {
        // in-memory implementation here..
    }
?>
\$\endgroup\$
  • \$\begingroup\$ Thank for you recommendation and suggestion, it really helps me a lot. Ya, I mixed both my data access object with entity together cause I think it is easier for me to understand since everything related to user can update, delete and even those complicated business logic I also can do it in same class without create extra interface or class. What is your point of view with this kind of design? What is the disadvantage of this design? \$\endgroup\$ – overshadow Aug 16 '14 at 9:34
  • \$\begingroup\$ @overshadow Trying to avoid creating extra interfaces/classes is just going to end up with having a bunch of monolithic, thousand-line classes that are impossible to read and maintain. It's also likely to lead to many concerns being held in one place: data access, data representation, business logic.. It's best to put these in separate layers. \$\endgroup\$ – Chris Hayes Aug 16 '14 at 9:38
1
\$\begingroup\$

Dependency injection looks better. It allows you to clearly separate the database and the other classes of your application. It would also help you test your application because you will be able to test your classes without hitting the real database.

I'd also try to decouple the classes you're using in your application and the fact that they're database entities. It doesn't look right that an user or an employee know the database they're persisted to. You should consider having a separate class that abstracts away the database and allows you to do all the operations you need to store and retrieve your entities.

\$\endgroup\$
  • \$\begingroup\$ Thank you for your suggestion. For decouple the classes, do you mean something like data access object that mentioned by Chris Hayes? \$\endgroup\$ – overshadow Aug 16 '14 at 9:47
  • \$\begingroup\$ Yes, exactly. Neither I am a PHP guy but I think that pattern could be very useful in your use case \$\endgroup\$ – mariosangiorgio Aug 16 '14 at 9:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.