PHPBuilder - Implementing the Singleton Pattern in PHP 5



RSS Twitter
Articles Tricks And Hacks

Implementing the Singleton Pattern in PHP 5

by: Octavia Andreea Anghel
|
November 23, 2010

As you probably know, in software engineering there is a set of design patterns that are universally tested, approved and accepted as advanced recipes for programming. One of these patterns is the Singleton design pattern, which is based on the mathematical concept of a singleton (a set with a single element). Part of the well-known Gang of Four (GoF) design patterns, it calls for restricting the instantiation of a class to one object. (Those who are familiar with design patterns may be interested to know that the Singleton pattern in itself is an implementation of the Responsibility pattern.)
Sometimes the Singleton pattern can help complete important programming tasks, but only you can decide where and when it fits your needs. As a pointer, the Singleton pattern fits well when you manage a shared resource -- a printer, a file manager, a database connection, loggers, and so on -- because your application should have only a single instance in order to avoid conflicting requests for the same resource and to minimize performance issues.
Before deciding to use the Singleton pattern, you should first answer "yes" to three main questions:
  1. Do you need concurrent access to a shared resource by the entire application?
  2. Will there be requests from multiple, disparate parts of the system?
  3. Do you need only one global object?
Figure 1 breaks the Singleton pattern down into programming concepts. It is a UML class diagram of a Singleton class.

Figure 1. Singleton Pattern UML Class Diagram
In this article, I explain how to implement the Singleton pattern in different ways for different purposes in PHP 5.

Implementing a Singleton Class Template

In this section, you will create a PHP Singleton class template. It will be a common PHP class, except that it will have only one instance and provide a global point to access it. Keeping this in mind, you can develop a Singleton PHP class as follows:
  1. Declare a private static member variable for storing the instance of that class. This is the object instance:
    private static $_instance = null;
  2. Lock down the class constructor by declaring it as private. This will make the class externally "uninstantiable":
    private function __construct() { }
  3. Prevent external instantiation of copies of Singleton class. Locking down clone and wakeup methods will prevent duplicate objects (clones).
    public function __clone() {
    trigger_error( "Cannot clone instance of Singleton pattern ...", E_USER_ERROR );
    }
    public function __wakeup() {
    trigger_error('Cannot deserialize instance of Singleton pattern ...', E_USER_ERROR );
    }
  4. Declare a public static method that creates a single instance of that class. It checks if an instance already exists. If it does, it returns the same instance each time it is called. Otherwise, it creates an instance, stores it in the static member variable and returns it.
    public static function getInstance()
    {
    if( !is_object(self::$_instance) )
    //or if( is_null(self::$_instance) ) or if( self::$_instance == null )
    self::$_instance = new self;
    //or, in PHP 5.3.0
    //if (empty(static::$_instance)) {
    // $class = get_called_class();
    // static::$_instance = new $class;
    //}
    return self::$_instance;
    }
Now, the Singleton class template is ready, and it looks like this:
class SingletonClass
{
//A static member variable representing the class instance
private static $_instance = null;
//Locked down the constructor, therefore the class cannot be externally instantiated
private function __construct() { }
//Prevent any object or instance of that class to be cloned
public function __clone() {
trigger_error( "Cannot clone instance of Singleton pattern ...", E_USER_ERROR );
}
//Prevent any object or instance to be deserialized
public function __wakeup() {
trigger_error('Cannot deserialize instance of Singleton pattern ...', E_USER_ERROR );
}
//Have a single globally accessible static method
public static function getInstance()
{
if( !is_object(self::$_instance) )
//or if( is_null(self::$_instance) ) or if( self::$_instance == null )
self::$_instance = new self;
//or, in PHP 5.3.0
//if (empty(static::$_instance)) {
// $class = get_called_class();
// static::$_instance = new $class;
//}
return self::$_instance;
}
}
For testing your Singleton class, you should add a trivial method to it, like this one:
//The singleton pattern ends here - from this point forward we have the methods of the class
//A simple method to echo something
public function test()
{
echo " 

I'm a method of a singleton class

"; }
Now, you can develop a simple test for the Singleton class. Your test should be focused on trying to create multiple instances of the Singleton class.
- This page tests the SingletonClass class -
 include_once('SingletonClass.php');
$instance_1 = SingletonClass::getInstance();
$instance_2 = SingletonClass::getInstance();
echo("First test:");
$instance_1->test();
echo("Second test:");
$instance_2->test();
//try to clone an instance
echo("Try to clone the singleton instance (if you see blank below, then you better check the logs):");
$cloned = clone $instance_1;
$cloned->test();
?>
The result of this test should output Figure 2.


Click here for larger image

Figure 2. The Output for Test Singleton Class
Note: The error messages returned by the clone and wakeup methods are available in the log folder of your Web container. (If you tested this under Apache HTTP Server, these errors are written in the error.txt file under the /logs folder.)

1
|
2
Next Page »

Comment and Contribute

Your comment has been submitted and is pending approval.

Author:
Octavia Andreea Anghel

Comment:



Comment:

(Maximum characters: 1200). You have characters left.