2

I came across this piece of code that's supposed to ensure that only one database connection is created per browser so that the application sees improved performance due to the reduced number of calls to the database.

I believe I do understand the logic how this is ensured but I just need to confirm that my understanding on this is correct and complete. So, please help me with the explanation details.

Also is there a better practice than this when making database connection/calls ?

class Database {
    private static $dsn = 'mysql:host=localhost;dbname=mydatabase';
    private static $username = 'dbuser';
    private static $password = 'dbpass';
    private static $db;

    private function __construct() {}

    public static function getDB ()
    {
        if (!isset(self::$db)) {
            try {
                self::$db = new PDO(self::$dsn,
                                 self::$username,
                                 self::$password);
            } catch (PDOException $e) {
                $error_message = $e->getMessage();
                include('../errors/database_error.php');
                exit();
            }
        }
        return self::$db;
    }
}
Taz
  • 3,718
  • 2
  • 37
  • 59
user481913
  • 1,022
  • 1
  • 13
  • 36
  • 2
    [Singleton pattern](http://en.wikipedia.org/wiki/Singleton_pattern) – raina77ow Nov 21 '12 at 17:41
  • @raina77ow i'm not sure what this is called but i notice that except for the only pdo object created inside the getDB() method, the user does not have the ability to create more DB objects... is this what you mean by the Singleton Pattern? – user481913 Nov 21 '12 at 17:48
  • Someone please provide me with a thorough explaination about why it has a private constructor and everything static... – user481913 Nov 21 '12 at 17:50
  • 1
    [Who needs Singletons](http://stackoverflow.com/questions/4595964/who-needs-singletons/4596323#4596323) – Gordon Nov 22 '12 at 08:43
  • +1 Thanks for that link Gordon... – user481913 Nov 23 '12 at 17:52

1 Answers1

4

As @raina77ow noted in a comment, this is called the Singleton pattern. Here's some explanation:

The point of being a Singleton is that no calling code can create more than one $db. And to provide global access from anywhere in your code to the created $db.

Static class variables exist as exactly one instance per class. Therefore you can't create multiple $db connections even if you could instantiate this class as an object.

Since there's no purpose to instantiating the class as an object (that would only be useful if the class had non-static variables that existed per object instance), the class constructor is not needed. To prevent calling code from being tempted to call new, the constructor is made private. (Strictly speaking, there would be no harm in doing so, because the only class variables are static anyway.)

Note that your implementation is missing the magic __clone and __wakeup methods. Without these your Singleton can still be cloned and unserialized. So technically, your Singleton is not enforcing singularity properly.

Here are some additional thoughts:

  • Singleton classes (or any classes with static usage) are notoriously difficult to integrate into automated testing. Since they're static, you can initialize them once and they retain their state for the duration of your test suite. If you use non-static classes, you can re-initialize them each time you use new to instantiate a new object.

  • An alternative design is to use a Registry pattern, and some kind of bootstrap for your application that creates a non-static db instance and stores it in the registry.

  • If you do use Singleton, it's sometimes recommended to declare the Singleton class final so no subclasses can override the behavior or get access to the private data.

  • Your database credentials are hard-coded as private data in the class definition. I wouldn't do that. If your Apache PHP handler gets misconfigured, users could see your PHP source code, and then they'd have your database password. Put the database connection parameters into a config file, and store the config file outside your Apache document root.

  • Outputting the db connection error message verbatim can reveal information to users. Log the PDO error message, but put out a friendly message for users like "we're experiencing a problem, please notify the site administrator."

  • You don't need to terminate PHP blocks with ?> in a class definition file. It adds a risk that you could have a space or a newline after the close, which will become whitespace in your application and throw off your layout. Those types of errors are maddening to track down.

Gordon
  • 312,688
  • 75
  • 539
  • 559
Bill Karwin
  • 538,548
  • 86
  • 673
  • 828
  • Thanks Bill, I'll look into all the points you mentioned and I'll get back to you later if i have additional doubts... – user481913 Nov 21 '12 at 18:00
  • I added some more content above to explain the static and private thing. – Bill Karwin Nov 21 '12 at 18:04
  • Thanks again, I guess I do understand the logic behind the static and private declarations now but i need to read up a bit on the singleton and regisry patterns to get a hang of how they work, so it may take some time.... – user481913 Nov 21 '12 at 18:14
  • 1
    +1 Thanks Bill and Gordon, for someone at my level there's a lot to digest here... I surely have a few follow up questions cropping up in my mind but I'll probably ask them after I've read through all the theory ... probably some might get answered or refined along the way while there might be a few new ones that get added. – user481913 Nov 23 '12 at 02:29
  • Glad to help, and yeah there is a lot to digest. Best of luck! Keep asking questions on StackOverflow. Cheers! – Bill Karwin Nov 23 '12 at 08:57