Singleton Design Pattern – Usage and Example in PHP

Nov 6th, 2010

Singleton design pattern is useful when we need a one-of-its-kind object. Only single instance of a single pattern class is possible. This kind of class is generally useful in resource handling or in other use case where we need single instance of Object. Database connection handling is one such example. Another very classic use case of singleton design pattern is for configuration option file. Global variable use can be replaced with singleton design pattern class.

I will show you the usage of singleton design pattern in configuration options. First, I will show you the old classic configuration file and its usage then I will move to Singleton design pattern based configuration file. I have merged the code of configuration file, HTML file and its application in one, so do not get confused.

Here is a small application for uploading file to server which is using normal array style configuration file. Think of line 3-6 as a config file, line 8-34 as a PHP file using config option, and rest is a HTML form.

<?php

// config file
// Without singleton class
$config['upload'] = 'C:/xampp/htdocs/uploads/';
// End config

class newClass {

	public function saveUploadedFile($file) {

		global $config;

		if (is_uploaded_file($file['upload']['tmp_name'])) {

                    if (move_uploaded_file($file['upload']['tmp_name'], $config['upload'].'/'.$file['upload']['name']))
                    {
                        echo 'File uploaded';
                    }
                    else
                    {
                        echo 'Error in upload.';
                    }
		}
	}

}


if (count($_FILES)) {
    $cls = new newClass;
    $cls->saveUploadedFile($_FILES);
}

?>

<form name="frm1" action="" method="post" enctype="multipart/form-data">

    <input type="file" name="upload" value="UploadFile">

    <input type="submit" name="submit1">
    
</form>

Here is a same small application written again for using singleton design pattern. Here also, line 1-36 is a config file, line 38-68 is a PHP class using config option and rest are HTML code.

<?php
// config file
// Use of singleton class
// Singleton Design Pattern example as a config file
class configSingleton {

    private static $_instance = null;

    public $upload = 'C:/xampp/htdocs/uploads/';

    private function  __construct() {
        // empty
    }

    public static function getInstance()  {
        
        if (self::$_instance == null) {
            
            $thisClass = __CLASS__;
            self::$_instance = new $thisClass;
        }

        return self::$_instance;

    }

    // Prevent even duplicate by cloning
    // Prevent users to clone the instance
    public function __clone()
    {
        trigger_error('Clone is not allowed.', E_USER_ERROR);
    }

}

// End Config file


// Singleton Design Pattern demo
class newClass {

	public function saveUploadedFile($file) {

                // Cannot call like this as Constructor is private
                // $config = new configSingleton();

		$config = configSingleton::getInstance();
                   
		if (is_uploaded_file($file['upload']['tmp_name'])) {

                    if (move_uploaded_file($file['upload']['tmp_name'], $config->upload.'/'.$file['upload']['name']))
                    {
                        echo 'File uploaded';
                    }
                    else
                    {
                        echo 'Error in upload.';
                    }
		}
	}

}

if (count($_FILES)) {
    $cls = new newClass;
    $cls->saveUploadedFile($_FILES);
}

?>

<form name="frm1" action="" method="post" enctype="multipart/form-data">

    <input type="file" name="upload">

    <input type="submit" name="submit1">

</form>

I have not split the code for few reasons: I was feeling lazy and I do not want to make this post very very long.

 
  1. November 30th, 2010 at 07:21 | #1

    Why not just make the __clone method `final private`? No need to write any extra code.

    Fatal error: Call to private base::__clone() from context ” …\test.php on line 9

    Also, I think that E_USER_ERROR might be too delecate of an error to throw if you are going to do it this way.

  2. November 30th, 2010 at 07:22 | #2

    Doh, forgot to check the box so I could get your answer

  3. November 30th, 2010 at 08:41 | #3

    @SeanJA
    You point seems convincing.
    I researched at few places to grasp good theory and get a good example and found that php.net has a best example code. So, that point is taken from here. I am following Aaron Saray’s book and Head first design pattern. Head first design pattern using Java for code explanation.

  4. November 30th, 2010 at 08:48 | #4

    The problem with the singleton on php.net is that I can still extend the class (as you would probably want to so you can have a singleton database connection, a singleton config object) and overwrite the clone method so that the singleton can be cloned.

    The example on wikipedia is a better one me thinks: http://en.wikipedia.org/wiki/Singleton_pattern#PHP

    I notice that they also have added final to the contstructor which would be an additional thing to stop the destruction of the singleton.

  5. November 30th, 2010 at 08:57 | #5

    @SeanJA
    I am not sure, I never thought of it, but Constructor cannot be overridden then what the use of ‘final’ at that place!

  6. November 30th, 2010 at 09:01 | #6

    @SeanJA
    According to wiki, in Java, Constructors cannot be synchronized, final, abstract, native, or static. http://en.wikipedia.org/wiki/Constructor_%28object-oriented_programming%29#Java
    Though the same is not written for PHP.

  7. November 30th, 2010 at 09:05 | #7

    You can ruin the clone method (and with some messing around you could also mess up the constructor). Here is how to mess up the clone method: https://gist.github.com/721098

  8. November 30th, 2010 at 09:09 | #8

    @Satya Prakash

    You can make constructors final in php. Because “PHP is not Java”

  9. November 30th, 2010 at 09:25 | #9

    @SeanJA
    Thanks for writing code accessible for public. I have noticed your point but not sure of its pros and cons and OOps concept around it the way Head first discuss it.
    I also have thought to put this http://goo.gl/PejKz on Github or Google code but not sure it is worth or not. I also though to improve it a little.

  10. November 30th, 2010 at 10:07 | #10

    @Satya Prakash I almost always throw my code up on github just because I can, it is good as a learning tool, as in “What was I thinking when I wrote this?”, or other people can come by and help you out by pointing out problem areas, or fork your code (on github) and make fixes to problems that they see, then push them back to you.

Comments are open for an year period. Please, write here on Facebook page.