Saturday, May 23, 2009

The singleton pattern using PHP

Some application resources are exclusive in that there is one and only one of this type of resource. For example, the connection to a database through the database handle is exclusive. You want to share the database handle in an application because it's an overhead to keep opening and closing connections, particularly during a single page fetch.
The singleton pattern covers this need. An object is a singleton if the application can include one and only one of that object at a time. The code below shows a database connection singleton in PHP5.

Singleton.php

<?php
require_once("DB.php");

class DatabaseConnection {
public static function get() {
static $db = null;
if ( $db == null )
$db = new DatabaseConnection();
return $db;
}

private $_handle = null;

private function __construct() {
$dsn = 'mysql://root:password@localhost/photos';
$this->_handle =& DB::Connect($dsn, array());
}

public function handle() {
return $this->_handle;
}
}

print("Handle = ".DatabaseConnection::get()->handle()."\n");
print("Handle = ".DatabaseConnection::get()->handle()."\n");
?>


This code shows a single class called DatabaseConnection. You can't create your own DatabaseConnection because the constructor is private. But you can get the one and only one DatabaseConnection object using the static get method.

The database connection singleton
The database connection singleton


The proof in the pudding is that the database handle returned by the handle method is the same between two calls. You can see this by running the code on the command line.
% php singleton.php
Handle = Object id #3
Handle = Object id #3
%
The two handles returned are the same object. If you use the database connection singleton across the application, you reuse the same handle everywhere.
You could use a global variable to store the database handle, but that approach only works for small applications. In larger applications, avoid globals, and go with objects and methods to get access to resources.
source: ibm.com

Design Patterns for PHP

3 comments:

Daniel said...

Who told you that there is in no way anyone could ever need to establish two simultaneous connections to a database? The singleton pattern is way too overused. There are very few instances that *really* warrants the usage of a singleton. Probably because it's conceptually easy to comprehend and people then think their application is well designed because they used a "design pattern". Typically it will be better to pass objects by argument instead of relying on objects that lie in the global namespace.

Giorgio said...

I appreciate the good use of php OO features, but I have to point out that there is no much difference (apart from the lazy initialization and syntactic suger) from $GLOBALS['instance'] and Singleton::getInstance(). It is the same difference between $object->var and $object->getVar().
Try googling for "Singletons are pathological liars", I'm sure you want to be a better developer than one that uses a bunch of Singletons. :)

Edgar said...

No, there is a very important difference. You can't be sure the object you get from globals is the same as you put in. Any code can mess with it. With the singleton you can be sure you get the same object everytime. That seems to be a huge difference to me. I agree it is most of the times better to pass the objects by argument, but sometimes this will overcomplicate the design.

Post a Comment