views:

1152

answers:

7

How would one create a Singleton class using PHP5 classes?

+11  A: 
/**
 * Singleton class
 *
 */
class UserFactory
{
 /**
  * Call this method to get singleton
  *
  * @return UserFactory
  */
 public static function Instance()
 {
  static $inst = null;
  if ($inst == null)
   $inst = new UserFactory();
  return $inst;
 }

 /**
  * Private ctor so nobody else can instance it
  *
  */
 private function __construct()
 {

 }
}

To use:

$fact = UserFactory::Instance();
$fact2 = UserFactory::Instance();

$fact == $fact2;

But:

$fact = new UserFactory()

Throws an error

:)

nlaq
to compare the two instances you should use === rather than ==. == will return true if $fact1 and $fact2 are both of the same class, but === only returns true if they are both the same instance of the same object.
Keith Twombley
A: 

It might be the correct answer to say "don't do it". See the related question What is so bad about Singletons. There are some good links to relevant articles in there.

Greg Hewgill
+10  A: 

You probably should add a private __clone() method to disallow cloning of an instance.

private function __clone() {}

If you don't include this method the following gets possible

$inst1=UserFactory::Instance(); // to stick with the example provided above
$inst2=clone $inst1;

now $inst1 !== $inst2 - they are not the same instance any more.

Stefan Gehrig
+4  A: 

Go here for some more patterns:

http://www.fluffycat.com/PHP-Design-Patterns/

AntonioCS
+4  A: 

PHP 5.3 allows the creation of an inheritable Singleton class via late static binding:

class Singleton
{
    protected static $instance = null;
    protected function __construct()
    {
        //Thou shalt not construct that which is unconstructable!
    }
    protected function __clone()
    {
        //Me not like clones! Me smash clones!
    }

    public static function getInstance()
    {
        if (!isset(static::$instance) {
            static::instance = new static;
        }
        return static::$instance;
    }
}

This solves the problem, that prior to PHP 5.3 any class that extended a Singleton would produce an instance of it's parent class instead of it's own one.

Now you can do:

class Foobar extends Singelton {};
$foo = Foobar::getInstance();

And $foo will be an instance of Foobar instead of an instance of Singleton.

Techpriester
Late static binding is indeed a very good thing in php 5.3. Too bad I still can't use it.
AntonioCS
A: 

Quick blog post Singleton pattern implementation for registry objects:

Singleton Pattern

eanimator
A: 

Supports Multiple Objects with 1 line per class:

This method will enforce singletons on any class you wish, al you have to do is add 1 method to the class you wish to make a singleton and this will do it for you.

This also stores objects in a "SingleTonBase" class so you can debug all your objects that you have used in your system by recusing the SingleTonBase objects.


Create a file called SingletonBase.php and include it in root of your script!

The code is

abstract class SingletonBase
{
    private static $storage = array();

    public static function Singleton($class)
    {
        if(in_array($class,self::$storage))
        {
            return self::$storage[$class];
        }
        return self::$storage[$class] = new $class();
    }
    public static function storage()
    {
       return self::$storage;
    }
}

Then for any class you want to make a singleton just add this small single method.

public static function Singleton()
{
    return SingletonBase::Singleton(get_class());
}

Here is a small example:

include 'libraries/SingletonBase.resource.php';

class Database
{
    //Add that singleton funtion.
    public static function Singleton()
    {
        return SingletonBase::Singleton(get_class());
    }

    public function run()
    {
        echo 'running...';
    }
}

$Database = Database::Singleton();

$Database->run();

And you can just add this singleton function in any class you have and it will only create 1 instance per class.

NOTE: You should always make the __construct private to eliminate the use of new Class(); instantiations.

RobertPitt