PHP Design Patterns: Singleton Pattern Example

php_logo_128The Singleton pattern is generally the first Design Pattern a developer is exposed to, because it solves a common problem and it is easy to understand and implement. Even though Design Patterns are language independent, each language often implements them differently. It is also important to remember that the context of the application can cause the implementation to change as well. Design Patterns are patterns not rules.

PHP allows you to create the Singleton in such a way that the internal code of the class can be agnostic. Changing the package or class name does not affect the Singleton implementation itself.

Traditionally you would create a Singleton like this:

Example 1.0 – Traditional implementation of Singleton

class DP_Singleton
{
    private static $_instance;
 
    /**
     * @return DP_Singleton
     */
    static function getInstance()
    {
        if(empty(DP_Singleton::$_instance)) {
            DP_Singleton::$_instance = new DP_Singleton();
        }
        return DP_Singleton::$_instance;
    }
 
    private function __construct ()
    {
        echo 'Singleton created.';
    }
}

Example 1.1 – Using the Singleton

// Cannot instantiate
//$singleton = new DP_Singleton();
 
/*
 * Output:
 * Fatal error: Call to private DP_Singleton::__construct() ...
 */
 
// Will instantiate a new class - first time its called
$singleton = DP_Singleton::getInstance();
 
/*
 * Output:
 * Singleton created
 */
 
// Will use already existing class
$singleton = DP_Singleton::getInstance();
 
/*
 * Output:
 *
 */

This works and is correct. However, we are not taking advantage of the PHP language. PHP has the notion of self in which it can reference the class it resides in. Static objects reside on the class reference not the instance.

By changing our code to this, we have now made our Singleton operation class independent.

Example 1.2 – Singleton using self.

class DP_Singleton
{
    private static $_instance;
 
    /**
     * @return DP_Singleton
     */
    static function getInstance()
    {
        if(empty(self::$_instance)) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
 
    private function __construct ()
    {
        echo 'Singleton created.';
    }
}

Later, if we need to refactor the package or name of our class, we do not need to refactor the Singleton implementation. Notice that I still have the comment indicating the return value. I have left this as the name of the class, for two reasons: 1) Many IDEs (such as Zend Studio) can provide auto-completion if it exists in the code; 2) for publishing documentation using PHPDocs.

Design Patterns as patterns not rules

If you look up design patterns by GoF or on Wikipedia, we have covered the definition, but we could go one step further and “extend” the pattern. For example:

Example 1.3 – Singleton with scope.

class DP_Singleton
{
    private static $_instance = array();
 
    /**
     * @return DP_Singleton
     */
    static function getInstance( $scope = 'default' )
    {
        if(empty(self::$_instance[$scope])) {
            self::$_instance[$scope] = new self();
        }
        return self::$_instance[$scope];
    }
 
    private function __construct ()
    {
        echo 'Singleton created.';
    }
}

Example 1.4 – Using the Singleton class with scope

// Cannot instantiate
//$singleton = new DP_Singleton();
 
/*
 * Output:
 * Fatal error: Call to private DP_Singleton::__construct() ...
 */
 
// Will instantiate a new class - first time its 
// called with 'default' scope
$singleton = DP_Singleton::getInstance();
 
/*
 * Output:
 * Singleton created
 */
 
// Will use already existing class
$singleton = DP_Singleton::getInstance();
 
/*
 * Output:
 *
 */
 
// Will instantiate a new class with our custom 
// scope 'my_scope'
$singleton = DP_Singleton::getInstance('my_scope');
 
/*
 * Output:
 * Singleton created
 */

We have introduced “scope” into our singleton. The nice thing about this addition is you can add it at anytime without affecting previously written code because scope is optional. Now if you have a need for another instance in the system, you can create one and other parts can use it as well.


  • No Related Post
bookmark bookmark bookmark bookmark bookmark bookmark bookmark bookmark bookmark bookmark bookmark bookmark
tabs-top


6 Responses to “PHP Design Patterns: Singleton Pattern Example”

  1. I’ve read about this before, but I’m unclear as to how this could be used in a real world code example.

  2. Rob says:

    @ernest

    Singletons generally come in handy during initialization: a single pointer to a Front Controller, configurations, a single access point to the database, etc. Singletons allow you to instantiate once and only once on demand. Until an instance of the class is needed it isn’t created. I may create, for example a configuration class, that when accessed loads from a Db or file. I only want this to happen once, so using a Singleton is a good option. Same is true with a database adapter or ActiveRecord class, if I want to ensure only once connection. Later when I need to access the class’s methods and properties, they will be available to me having to pass it in to the method or store it in some static property on another class.

    If you need to instantiate a class, but only need once instance, use the Singleton, otherwise create a static class. Also if you ever intend on extending that class it is best to build it up as a Singleton. PHP allows you to extend static classes. Not all languages support this ability. So I generally tend to stick to this rule.

  3. Timur I. says:

    Great! Thank you very much!
    I always wanted to write in my site something like that. Can I take part of your post to my blog?
    Of course, I will add backlink?

    Sincerely, Reader

  4. jj says:

    I think your examples are all mixed up. Your first example already uses the self:: that you introduce for the second example, and it also has the scope that you introduce at the end of the post.

  5. Rob says:

    Thanks. I made the corrections.

  6. Adam says:

    Just as another approach…
    Tried this?…

    Step 1: Create your static class and make the __construct() function protected.
    e.g protected __construct();

    Step 2: Create the PHP5 __autoloader() function and within it do the following:

    function __autoload($class){
    require_once($classRoot.”/$class.php”);
    if(method_exists($class,’__construct’)){
    eval(“class al_$class extends $class{function __construct(){parent::__construct();}}new al_$class;”);}

    So basically… the concept is that the __construct() is protected so it will never run via the “new” request.

    The Autoloader then creates an additional class on the fly that extends the one we are calling and then runs its construct itself.

    This way you don’t need to keep doing myClass::getInstance();

    I’ve not printed this idea anywhere else so feel free to get back in touch and let me know if this is feasible… etc (in your opinion).

    Thanks for your examples though, was a good read.