PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

Magic Methods> <Object Iteration
Last updated: Fri, 02 May 2008

view this page in

Patterns

Patterns are ways to describe best practices and good designs. They show a flexible solution to common programming problems.

Factory

The Factory pattern allows for the instantiation of objects at runtime. It is called a Factory Pattern since it is responsible for "manufacturing" an object. A Parameterized Factory receives the name of the class to instantiate as argument.

Example #1 Parameterized Factory Method

<?php
class Example
{
    
// The parameterized factory method
    
public static function factory($type)
    {
        if (include_once 
'Drivers/' $type '.php') {
            
$classname 'Driver_' $type;
            return new 
$classname;
        } else {
            throw new 
Exception ('Driver not found');
        }
    }
}
?>

Defining this method in a class allows drivers to be loaded on the fly. If the Example class was a database abstraction class, loading a MySQL and SQLite driver could be done as follows:

<?php
// Load a MySQL Driver
$mysql Example::factory('MySQL');

// Load a SQLite Driver
$sqlite Example::factory('SQLite');
?>

Singleton

The Singleton pattern applies to situations in which there needs to be a single instance of a class. The most common example of this is a database connection. Implementing this pattern allows a programmer to make this single instance easily accessible by many other objects.

Example #2 Singleton Function

<?php
class Example
{
    
// Hold an instance of the class
    
private static $instance;
    
    
// A private constructor; prevents direct creation of object
    
private function __construct() 
    {
        echo 
'I am constructed';
    }

    
// The singleton method
    
public static function singleton() 
    {
        if (!isset(
self::$instance)) {
            
$c __CLASS__;
            
self::$instance = new $c;
        }

        return 
self::$instance;
    }
    
    
// Example method
    
public function bark()
    {
        echo 
'Woof!';
    }

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

}

?>

This allows a single instance of the Example class to be retrieved.

<?php
// This would fail because the constructor is private
$test = new Example;

// This will always retrieve a single instance of the class
$test Example::singleton();
$test->bark();

// This will issue an E_USER_ERROR.
$test_clone = clone $test;

?>


Magic Methods> <Object Iteration
Last updated: Fri, 02 May 2008
 
add a note add a note User Contributed Notes
Patterns
shane dot harter at midwayproducts dot com
13-May-2008 12:00
Re: Chris

Question re:  // Mangle the arguments into an array

Why not just use func_get_args() ? Am I missing something?

I mean, (no offense) but generally speaking I'm not a fan of what you put together.

I can see the benefit of abstracting the plumbing needed for a singleton in a common base class.

So I understand your thinking.

But I disagree with it. IMO creating a class hierarchy is about properly modeling a system (in the case of an event model) or an entity (in the case of a data model).

So instead of using inheritance to better solve a problem domain, I'm using it to handle an implementation detail.

IMO, creating an ISingleton interface to enforce continuity, and a code template of an empty class w/ all the required singleton programming would be much better.
someone at somewhere dot com
05-May-2008 01:20
If you want a singleton and you don't mind on throwing a stop error/exception when a 2nd instace is created instead of returning the already created object, then this code works with subclassing and without getInstace alike functions (just with __construct)

<?php

class SINGLETON
{
   
// the array for checking the created instances
   
protected static $singletons = array ();

   
// make it final so extended classes cannot override it
   
final public function __construct ()
    {
       
$classname = get_class ( $this );

        if ( ! isset (
self::$singletons[$classname] ) )
           
// instead of $this it could be any value since we are checking for isset, but a reference to the object may be useful in a possible improvement, somewhat
           
self::$singletons[$classname] = $this;
        else
           
// your favorite stop error here
           
trow new Exception ();
    }

   
// final as well, no overriding, plus protected so it cannot be called
   
final protected function __clone () {}
}

class
X extends SINGLETON
{
   
//...
}

class
Y extends X
{
   
//...
}

$x = new X ();
$y = new Y ();

$a = new X (); // execution stops, as an instance of X is created already

$b = new Y (); // execution stops, as an instance of Y is created already, it DOES NOT give problems with X, despite extending X

?>

so, if it is ok to stops the execution, this method is way simpler

it must stops the execution because no matter what, __construct will return a reference to the new object, always, so if the script goes on further you will have effectively 2 instances (as a matter of fact, the code above only checks the existence of another object from the same class, it does not prohibit the creation of a new one)

hth
Chris
18-Apr-2008 09:07
I cannot belive I was so stupid with my first note on this...

As any Singleton class forces a design pattern on to the user, and is really just a helper class for that design pattern, there is no reason not to force them to mangle any arguments into an array, which allows me to get rid of the use of the ReflectionClass and allows protected constructors.

If someone can delete the first note to hide my shame that would be great, and this bit of this one upto the ----- marker below :D

To save people the trouble of finding my previous note:

-----

This is a Singleton helper class inspired by Mattlock's Singleton class with interface.

It has the advantages of:

1) It uses only a single abstract class instead of an interface and class definition.
2) It allows for multiple instances of classes where you only wish to have one of any instance initialised with certain arguments such as connections to different databases, they may use the same class, but there will be one instance for each database.

This method should allow multiple child classes to extend the Singleton class, and only requires a small about of argument mangling to make it work.

<?php

abstract class Singleton
{
    static abstract public function
getInstance();

    static final protected function
getClassInstance($klass, $args=NULL)
    {
       
// Initialize array for $instances
       
if(self::$instances === NULL)
           
self::$instances = array();

       
// Initialize array for instances of $klass
       
if(!array_key_exists($klass, self::$instances))
           
self::$instances[$klass] = array();

       
// Create key from args
       
$key = serialize($args);

       
// Instantiate $klass
       
if(!array_key_exists($key, self::$instances[$klass]))
        {
               
self::$instances[$klass][$key] = new $klass($args);
        }

       
// Return instance of $klass
       
return self::$instances[$klass][$key];
    }

    static private
       
// Storage for all instances of Singleton classes
       
$instances;
}

final class
MySingleton extends Singleton
{
    static public function
getInstance()
    {
        return
Singleton::getClassInstance(__CLASS__);
    }

   
// Construct should be protected.
   
protected function __construct() {}
}

final class
NamedSingleton extends Singleton
{
    public
       
$name;

   
// Default arguments here NOT constuctor to prevent dupilicate instances.
   
static public function getInstance($name = 'Default')
    {
       
// Mangle the arguments into an array
       
$args = array('name' => $name);
        return
Singleton::getClassInstance(__CLASS__, $args);
    }

   
// Constructor must accept a single array containing all the arguments, if it wants to get any.
   
protected function __construct($args)
    {
       
$this->name = $args['name'];
    }
}

echo
'<pre>';

$a = MySingleton::getInstance();
$b = MySingleton::getInstance();
var_dump($a);
var_dump($b);

$c = NamedSingleton::getInstance();
$d = NamedSingleton::getInstance('Default');
$e = NamedSingleton::getInstance('Default');
var_dump($c);
var_dump($d);
var_dump($e);

echo
'</pre>';

?>
Chris
18-Apr-2008 07:11
This is an extension to Mattlock's Singleton class and interface.

It has a number of advantages:

1) It uses a single abstract class instead of an interface and class definition, which to me is cleaner.
2) It allows for multiple instances of one class where you only wish to have one of any instance initialised with certain arguments. For example a File class representing a file on the system, there will be multiple files, but you will only want one instance of the File class for each individual file.

but a number of disadvantages:

1) The use of ReflectionClass is far from ideal, but I cannot find a better way to initialise an "unknown" class with arguments to the constructor, without requiring another 'utility' method in the child class.
2) The __construct method of child classes MUST be declared 'public' so that the ReflectionClass can instantiate it.

if there is a good way to instantiate a class in a function that has its name as a string and an array holding its arguments, without using eval etc, please tell me :D

<?php

abstract class Singleton
{
    static abstract public function
getInstance();

    static final protected function
getClassInstance($klass)
    {
       
// Initialize array for $instances
       
if(self::$instances === NULL)
           
self::$instances = array();

       
// Get arguments and remove $klass
       
$args = func_get_args();
       
array_shift($args);

       
// Create key from args
       
$key = serialize($args);

       
// Initialize array for instances of $klass
       
if(!array_key_exists($klass, self::$instances))
           
self::$instances[$klass] = array();

       
// Instantiate $klass using reflection and store under $key
       
if(!array_key_exists($key, self::$instances[$klass]))
        {
            if(
count($args) > 0)
            {
               
$reflect = new ReflectionClass($klass);
               
self::$instances[$klass][$key] = $reflect->newInstanceArgs($args);
            }
            else
            {
               
// ReflectionClass cannot pass arguments to classes with no constructor.
               
self::$instances[$klass][$key] = new $klass();
            }
        }

       
// Return instance of $klass
       
return self::$instances[$klass][$key];
    }

    static private
       
// Storage for all instances of Singleton classes
       
$instances;
}

class
MySingleton extends Singleton
{
    static public function
getInstance()
    {
        return
Singleton::getClassInstance(__CLASS__);
    }
}

class
ArgSingleton extends Singleton
{
    public
       
$arg;

   
// Default arguments here NOT constuctor to prevent dupilicate instances.
   
static public function getInstance($arg = 'Default')
    {
        return
Singleton::getClassInstance(__CLASS__, $arg);
    }

    public function
__construct($arg)
    {
       
$this->arg = $arg;
    }
}

echo
'<pre>';

$a = MySingleton::getInstance();
$b = MySingleton::getInstance();
var_dump($a);
var_dump($b);

$c = ArgSingleton::getInstance();
$d = ArgSingleton::getInstance('Default');
$e = ArgSingleton::getInstance('Default');
var_dump($c);
var_dump($d);
var_dump($e);

echo
'</pre>';

?>
Chris N.
07-Apr-2008 09:27
I have read much of the debate between the singleton pattern and global variables.  I think there are two advantage the singleton has over a global variable.

1.) The singleton can provide protection of the data it holds.  The singleton class can define methods that will proper validate and store data.

2.) A singleton it more maintainable in two ways.  Changing the underlying data structure, say a string to an array, will take much less effort using a singleton than using a global variable where you would have to find every time the global variable is modified (which can be mitigated with regular expressions).  Second, the global variable can be changed and modified at any point in your code base which can cause problems with debugging large code bases, or code that relies on different libraries.

A practical example would be a way to log messages in an application.

With a global variable you can do:
<?PHP
$g_log
= '';
// or
$g_log = array();

// But at any point $log can be wiped out or changed. i.e.

$g_log = 42;

// Where as a singleton can't in inadvertently lose data.
class Log {
   public static function
instance() {
      static
$_instance = null;
      if (
is_null($_instance)) {
        
$_instance = new Log();
      }
      return
$_instance;
   }

   public function
logMsg($s) {
     
// Validate
      // Now add
  
}
}

$s_log = Log::instance();

// So if happens somewhere, unexpectedly
$s_log = 42;

// You will still have your log in the Log class and
$s_log->log("Hello World!");

/* Where as if $g_log was originally a string and you
wanted to change it to a global you would have to change */
$g_log .= 'Hello World!';
// to
$g_log[] 'Hello World!';
?>

If you change the underlying way in which the Log class stores the messages the above statement will not have to be changed.

If you want the speed or don't care about the security then use a singleton.  If you want the security or maintainability then use a singleton.

Finally, the best thing you can do is use a consistent coding style throughout your code no matter what approach you take.
Mattlock
21-Feb-2008 08:16
This allows for singleton functionality via class extension, and does not use any shady functions like eval.

<?php
interface ISingleton {
    public static function
GetInstance();
}

class
Singleton implements ISingleton {
    public static function
GetInstance($class='Singleton') {
        static
$instances = array();
       
        if (!
is_string($class)) {
            return
null;
        }
       
        if (
$instances[$class] === null) {
           
$instances[$class] = new $class;
        }
       
        return
$instances[$class];
    }
}

class
Mars extends Singleton implements ISingleton {
    public static function
GetInstance() {
        return
Singleton::GetInstance(get_class());
    }
}

class
Neptune extends Singleton implements ISingleton {
    public static function
GetInstance() {
        return
Singleton::GetInstance(get_class());
    }
}

$x = Mars::GetInstance();
echo
'<pre>'.print_r($x,true).'</pre>';

$x = Neptune::GetInstance();
echo
'<pre>'.print_r($x,true).'</pre>';
?>
me at chrisstockton dot org
17-Jan-2008 09:55
For anyone who reads: tims57 at yahoo dot com

Please let me show everyone a example of how a global variable is nothing like a singleton pattern. Take into considering the following. A global variable, cares not the state of its contents, it is only a container. If it contains a instance, a boolean, or a integer, it is all the same to it as PHP is dynamically typed it would be very easy for a global variable to be overridden by some dynamically loaded module in a complicated architecture, which could in turn cause a instance that maintains account or billing data to destruct before values are written to it.

The singleton is a means of protecting the instance to a single instantiation.

A global variable offers no such protection, it is only a container for a value.

<?php

$unreliableInstanceNotProtectedAtAll
= new StdClass;

class
Singleton
{
    static private
$_instance;
    private
$_foo = 'foo';
    private function
__construct() {}
    static public function
getInstance() {
        return isset(
self::$_instance) ?
           
self::$_instance : self::$_instance = new self();
    }
    public function
updateFoo($foo) {
       
$this->_foo = $foo;
    }
    public function
getFoo() {
        return
$this->_foo;
    }
}

/** Singleton offers protection from being instantiated multiple times */
// file_2481_r4.php, the early foo module not used except under certain circumstances
$foo = Singleton::getInstance();
var_dump($foo->getFoo()); // foo
$foo->updateFoo('bar');
var_dump($foo->getFoo()); // bar

// file_1444114_r1.php (author has no idea that file_2481_r4.php was loaded by
// the "foo" module", doesn't matter because the class will be instantiated only once
$foo = Singleton::getInstance();
var_dump($foo->getFoo()); // bar

/** Global variable just contains a instance, has no care for what it contains */
// file_2481_r4.php, the early foo module not used except under certain circumstances
$unreliableInstanceNotProtectedAtAll->foo = 'foo';

// file_1444114_r1.php (author has no idea that file_2481_r4.php was loaded by
// the "foo" module", doesn't matter because the class will be instantiated only once
$unreliableInstanceNotProtectedAtAll = new StdClass;
$unreliableInstanceNotProtectedAtAll->foo = 'bar';

?>
Alexandre at dontspamme gaigalas dot net
09-Jan-2008 01:01
Simplest PHP5 singleton implementation ever:

<?php
class Some_Class
{
    static private
$_i;
    private function
__construct()
    {
    }
    static public function
singleton() {
        return isset(
self::$_i) ? self::$_i : self::$_i = new self();
    }
}
?>
tims57 at yahoo dot com
31-Dec-2007 12:57
For anyone who reads: me at chrisstockton dot org

The note being refered to by that post is actually correct. A singleton provides essentially the same functionality as a global variable refering to an object combined with code to create the object at first use or application initialization. Using them is just a much more involved and difficult to follow technique involving class instantiation. Although perhaps appropriate in some circumstances, for many uses the global variable approach makes more sense.

The note being refered to is also correct regarding design patterns. Using design patterns and using interfaces should not be confused, they are nothing the same. Authors of 'pay-for software' (those 'large scale enterprise applications') have to get our laughs some way or another!

One final point neither note writer seems to get. PHP 5 accommodates many architectures, and is quite valuable for building scalable applications, even though it is still (thank God) free. PHP is now one of the 'big guys', and it needs these object oriented capabilities, even though they might be confusing to some.
me at chrisstockton dot org
25-Sep-2007 01:23
For anyone who reads: anonymous at world4ch dot org

Please do not confuse the singleton for a global variable, they are nothing the same. The global keyword is a way to extract a variable from the global scope into your local scope. A singleton is a way to control class instantiation, independent of scope to a single instance.

In addition note the importance in design patterns, the ability to interchange interfaces and abstraction to allow easy adaption to a variety of needs and specifications through a single means of access is invaluable to many large scale enterprise applications. Specially pay-for software that has many system architectures to accommodate. However, the comment makes a good point to implement as necessary, the many principles don't apply to every problem domain. Do not conform your problem to a pattern, implement a pattern to your problem.
anonymous at world4ch dot org
16-Jul-2007 01:37
A singleton is the "enterprise professional scalable business solution" version of a global variable. It'd be a good idea if this were the IOCCC, but since it isn't, it's better to simply say:

global $lol;

It's also faster and more maintainable, and has the same advantages and disadvantages.

Also, I'll advise against all "enterprise object-oriented industry-standard design patterns". Some of these patterns are correct, but their existence is not. Programming is not about copypasta. It's about thinking, abstracting and combinating. If you can't think of these patterns for yourself when you need them — and in the case of needing them, manage to abstract them so that your code doesn't become a copypasta fest, then you shouldn't be programming in the first place.

Furthermore, the existence of software patterns is a proof of the object-oriented model shortcomings. You shouldn't ever need to do any copypasta in your code. If something is done two or more times, you abstract it. And the language should support a way for you to. There's no reason for a "design pattern" to exist more than once, and since they are trivial (they better be trivial to you, if you are programming), you don't need to study them.

The best advice I can give you is that instead of reading "design patterns", you read Structure and Interpretation of Computer Programs (SICP), a book freely available from MIT where you will learn what you need to program properly in any programming language.
dario [dot] ocles [at] gmail [dot] com
18-Jun-2007 03:09
This's a example of Composite Pattern:

<?php
abstract class Graphic{
    abstract public function
draw();
}

class
Triangle extends Graphic{
    private
$name = '';

    public function
__construct($name = 'unknown'){
       
$this->name = $name;
    }

    public function
draw(){
        echo
'-I\'m a triangle '.$this->name.'.<br>';
    }
}

class
Container extends Graphic{
    private
$name = '';
    private
$container = array();

    public function
__construct($name = 'unknown'){
       
$this->name = $name;
    }

    public function
draw(){
        echo
'I\'m a container '.$this->name.'.<br>';
        foreach(
$this->container as $graphic)
           
$graphic->draw();
    }

    public function
add(Graphic $graphic){
       
$this->container[] = $graphic;
    }

    public function
del(Graphic $graphic){
        unset(
$this->container[$graphic]);
    }
}

$tri1 = new Triangle('1');
$tri2 = new Triangle('2');
$tri3 = new Triangle('3');

$container1 = new Container('1');
$container2 = new Container('2');
$container3 = new Container('3');

$container1->add($tri1);
$container1->add($tri2);
$container2->add($tri3);

$container3->add($container1);
$container3->add($container2);

$container3->draw();
?>

The above example will output:

I'm a container 3.
I'm a container 1.
-I'm a triangle 1.
-I'm a triangle 2.
I'm a container 2.
-I'm a triangle 3.

Dario Ocles.
baldurien at bbnwn dot eu
09-May-2007 03:49
uvillaseca at yahoo dot es :

Yes. In PHP singleton are dependent to a start page - unless if php is runt from a console - thus :

<?php
final class Foo {
  private
__construct() {
   
// read some static file like configuration file
 
}
  public static function
getInstance() {
    static
$instance = null;
    if (
null === $instance) $instance = new Foo();
    return
$instance;
  }
}
?>

The file is read each time someone hit the startpage (say "index.php" which would include "Foo.php", and which would call Foo::getInstance()).

Use of cache like APC may allow you to achieve a singleton which would work on the whole server instead of each incoming connexion (an incoming connexion that read a php page, like index.php, will run the script, use the singleton, read the static file, each time while if the singleton was stored like a global instance among each incoming transaction, then the file would be read only once).

However, it is hard to do some as you are not in Java and J2EE, where such is valid and thread safe :

<?php // note : this is java!
public final class Foo {
  private
Foo() {/*read our file*/}
  private static final
Foo instance = new Foo();
  public static final
Foo getInstance() {
    return
instance;
  }
}
?>
Because when Java load the class, a lock is acquired so that we only have one call to the constructor, this is equivalent :
<?php // note : this is java!
public final class Foo {
  private static final
Object synchrotron = new Object();
  private
Foo() {/*read our file*/}
  private static
Foo instance;
  public static final
Foo getInstance() {
   
synchronized (synchrotron) {
     
// force the thread to wait here
      // eg: only one thread is in that block
     
if (instance == null) {
       
instance = new Foo();
      }
      return
instance;     
    }
  }
}
?>
The comparison with Java is useful, because it means that you have some work to do to achieve a singleton that would work on the whole server instead of only each incoming connexion :

If you use APC, like this :

<?php
final class Foo {
  private
__construct() {
   
// append "blah" to a file
 
}
  public static function
getInstance() {
    if (
false === ($o = apc_fetch(__FUNCTION__)) {
     
$o = new Foo();
     
apc_store(__FUNCTION__, $o);
    }
    return
$o;
  }
}
?>

This would work. But, when two incoming connexion arise at the same exact moment, then you will append "blah" twice.

As for the one that said that singleton are a class with static method, no it is not. A singleton is polymorphic, where static method are simply the equivalent with a class namespace of function.

If you have a method or function that expect an object implementing interface A, then you will be able to use singleton implementing interface A.
Dave Miller
25-Mar-2007 03:12
Here's a way to make singleton classes with no extra code other than "extends Singleton" - if you use __AutoLoad() and keep each class in a separate file that is...

<?php

abstract class Singleton {
 
 
// Cannot be instantiated by any other class
 
protected function __Construct() { }
 
 
// Cannot be cloned ever
 
private function __Clone() { }
 
 
// Create/fetch an instance of the class
 
static public function getInstance($ClassName = null) {
   
    static
$Instance;
   
    if (
$Instance) {
      return
$Instance;
    } elseif (
$ClassName) {
     
$Instance = new $ClassName;
      return
$Instance;
    } else {
      return
null; // or throw exception if you want...
   
}
   
  }
 
}

function
__AutoLoad($ClassName) {
  include
"$ClassName.php";
  if (
is_subclass_of($ClassName, 'Singleton')) {
    eval(
$ClassName.'::getInstance($ClassName);');
  }
}

// ClassName.php
class ClassName extends Singleton {
 
// ... Code ...
}

// To use
$a = ClassName::getInstance();
$a->MyFunc();

?>

Of course you could do this differently - the point is that you can use __AutoLoad() to tell the single what class it is, unlike some other ways where this is done manually every time you define a singleton class.
david at bagnara dot org
28-Dec-2006 12:45
Thanks for the example below of an extendable Singleton. I have enhanced it a little so the derived class does not need to implement any functions. The technique to get an instance is now
$x = Singleton::connect( "derived_class_name")

<?php
class Singleton
{

/*
    How to use:
        extend new class from singleton
    To connect:
        $x = Singleton::connect( "CLASSNAME" ) ;
 */
   
private static
       
$instanceMap = array();

   
//protected constructor to prevent outside instantiation
   
protected function __construct()
    {
    }
  
   
//deny cloning of singleton objects
   
public final function __clone()
    {
       
trigger_error('It is impossible to clone singleton', E_USER_ERROR);
    }

    public function
connect(    // return a (reference to) a single instance of className
                   
$className  // name of a class derived from Singleton
                   
)
    {
       
// see if class already constructed
       
if(!isset(self::$instanceMap[$className]))
        {
           
// if not then make one
           
$object = new $className;
           
//Make sure this object inherit from Singleton
           
if($object instanceof Singleton)
            {
               
// save in static array
               
self::$instanceMap[$className] = $object;
            }
            else
            {
                throw
SingletonException("Class '$className' do not inherit from Singleton!");
            }
        }
       
// return reference to single instanace of className
       
return self::$instanceMap[$className];
    }
}

?>

<?php

class A extends Singleton
{
    protected
$rndId;
  
    protected function
__construct()
    {
       
$this->rndId = rand();
    }
  
    public function
whatAmI()
    {
        echo
'I am a ' . get_class( $this ) . ' (' . $this->rndId . ')<br />';
    }
}

class
B extends A
{
}

$a = Singleton::connect( "A" );
$b = Singleton::connect( "B" );
$a->whatAmI();// should echo 'I am a A(some number)
$b->whatAmI();// should echo 'I am a B(some number)

unset( $a ) ;

$c = Singleton::connect( "A" );
$d = Singleton::connect( "B" );

$c->whatAmI();// should echo 'I am a A(same number as above)
$d->whatAmI();// should echo 'I am a B(same number as above)

$a = new A();// this should fail
$b = new B();// this should fail

?>
eyvindh79 at gmail dot com
06-Dec-2006 09:48
A pure extendable(multiple sublevels) Singleton class in PHP seems impossible at the moment because of the way PHP handles static inheritance, but my class is close to what i want.

Very simple usage:

<?php
class Test extends Singleton {

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

}
?>

Singleton class implementation:

<?php
class Singleton {

   
/***********************
     * HOW TO USE
     *
     * Inherit(extend) from Singleton and add getter:
     *
     *  //public getter for singleton instance
     *     public static function getInstance(){
     *        return Singleton::getSingleton(get_class());
     *    }
     *
     */
   
   
private static $instanceMap = array();

   
//protected getter for singleton instances
   
protected static function getSingleton($className){
        if(!isset(
self::$instanceMap[$className])){
           
           
$object = new $className;
           
//Make sure this object inherit from Singleton
           
if($object instanceof Singleton){   
               
self::$instanceMap[$className] = $object;
            }
            else{
                throw
SingletonException("Class '$className' do not inherit from Singleton!");
            }
        }
       
        return
self::$instanceMap[$className];
    }   
   
   
//protected constructor to prevent outside instantiation
   
protected function __construct(){
    }
   
   
//denie cloning of singleton objects
   
public final function __clone(){
       
trigger_error('It is impossible to clone singleton', E_USER_ERROR);
    }   
}
?>

Just a simple test case:

<?php
class A extends Singleton {
   
    protected
$rndId;
   
    protected function
__construct(){
       
$this->rndId = rand();
    }   
   
    public function
whatAmI(){
        echo
'I am a A('.$this->rndId.')<br />';
    }

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

}

class
B extends A {

    public function
whatAmI(){
        echo
'I am a B('.$this->rndId.')<br />';
    }
   
    public static function
getInstance(){
        return
Singleton::getSingleton(get_class());
    }

}

$a = A::getInstance();
$b = B::getInstance();

$a->whatAmI();// should echo 'I am a A(some number)
$b->whatAmI();// should echo 'I am a B(some number)

$a = A::getInstance();
$b = B::getInstance();

$a->whatAmI();// should echo 'I am a A(same number as above)
$b->whatAmI();// should echo 'I am a B(same number as above)

$a = new A();// this should fail
$b = new B();// this should fail

?>

I hope this helps.
-Eyvind-
suki at psychosensor dot de
29-Sep-2006 05:38
cortex is right - it took me hours to figure it out. None the less it's sometimes useful to let one sigleton class extend another. You can achieve this by only using static attributes:

<?php
 
class A {
    private static
$value = 0;
    private static
$instance = null;
   
    private function
__construct() {
     
$this->set(time());
    }
   
    public static function
getInstance() {
      if (
is_null((self::$instance))) {
       
$class_name = __CLASS__;
       
self::$instance = new $class_name;
      }
     
      return
self::$instance;
    }
   
    private function
set($i) {
     
self::$value = $i;
     
$this->out();
    }
   
    public function
out() {
      echo
self::$value;
    }
  }

  class
B extends A {
    public static
$instance = null;
   
    public static function
getInstance() {
     
parent::getInstance();
      if (
is_null(self::$instance)) {
       
$class = __CLASS__;
       
self::$instance = new $class;
      }
      return
self::$instance;
    }
  }

 
$b = B::getInstance();
 
$b->out();
?>

This will output the current time twice. If $value isn't static, the call to $b->out() will output 0. Maybe it can save someone some time...
Dennis
11-Aug-2006 12:19
An easy way to have your singleton persistent between page loads:

/**
 *    Returns an instance of the singleton class.
 *    @return    object        The singleton instance
 */
public static function _instance()
{
    // Start a session if not already started
    Session::start();
   
    if ( false == isset( $_SESSION[ self::$_singleton_class ] ) )
    {
        $class = self::$_singleton_class;
        $_SESSION[ self::$_singleton_class ] = new $class;
    }
   
    return $_SESSION[ self::$_singleton_class ];       
}

/**
 *    Destroy the singleton object. Deleting the session variable in the
 *    destructor does not make sense since the destructor is called every
 *    time the script ends.
 */
public static function _destroy()
{
    $_SESSION[ self::$_singleton_class ] = null;
}

/**
 *    Initialize the singleton object. Use instead of constructor.
 */
public function _initialize( $name )
{
    // Something...
}

/**
 *    Prevent cloning of singleton.
 */
private function __clone()
{
    trigger_error( "Cloning a singleton object is not allowed.", E_USER_ERROR );
}

private static $_singleton_class = __CLASS__;
daniel at basegeo dot com
02-Aug-2006 12:55
Ubaldo, you cannot expect to get the same instance using the Singleton pattern on different runs of the script.

Each time you execute index.php it's a new runtime environment. It's like executing several times Notepad, each run is unrelated to the others.

As your scripts grow in size, and you modularize code used on many pages into classes and libraries you'll realize how useful the Singleton pattern is. For instance, you can create a database abstraction class that you can call from many places and always be asured it's a single instance... in this case that means a single connection to the database.

Hope this clarifies the issue for you.
uvillaseca at yahoo dot es
07-Jul-2006 09:59
I don't know if it's useful has a singleton that is a singleton only inside a script. By example, having the following scripts:

<?php
//index.php
require_once("Singleton.php");
$p = Singleton::getInstance();
$s = Singleton::getInstance();
?>

<?php
//Singleton.php
class Singleton {
    private static
$instance;

    private function
__construct() {
       
    }
    public static function
getInstance() {
        if(!isset(
self::$instance)) {
            echo
'creating singleton';
           
self::$instance = new self;
        }
        return
self::$instance;
    }
}
?>

Calls to index.php always returns the message 'creating singleton', so a new instance of the class is created for each call to index.php; and this is not the behaviour that I'd expect.

Best regards,

Ubaldo
cortex at pressemicro dot net
02-Jun-2006 01:27
It's often forgotten, but a singleton class MUST be final. So it's useless to have a base class that implements the pattern and to inherit of it. That's why it's called a pattern and not a class library.

Here a little example that will show why.

<?php
class A {
// singleton pattern with getInstance static method
private $var; // A ressource variable
function __construct() {
   
$this->var = "get a ressource that could only  be taken one time by process";
}
}

class
B extends A {
// singleton pattern
function __construct() {
   
parent::__construct();
}
}

$anA = A :: getInstance();
$aB = B :: getInstance(); // try to get a second ressource, :(

?>

When developping class A, you may have think to be the only one with a $var ressource, but it's completly wrong. As $aB is an A (Think that there is two A instanciate and one with more than just A), $anA and $aB will have a different ressource variable and thus two different database connection for eg.

You'd never know how will be used your code, so you need to make it strong. This is the way of poo thinking.
lycboy at gmail dot com
29-Apr-2006 03:15
I don't agree to take a class with only static members and static methods as a 'singleton'. According to GoF's book, the singleton pattern means a class that only have one instance. A class containing only static members and functions still can be instantiated and extended, it have multiple instances. Consider the code below:
<?php

class StaticTest
{
    private static
$_test = "aaa";
   
    public static function
test()
    {
        echo
self::$_test;
    }
}

$obj = new StaticTest();

?>
The code will not report errors(although it's useless). So there can be many instances of the class.

It's reasonable that there is a class that create and store a unique instance of another class. Such as:
<?php

class A
{
    private
$_id = 0;
    public function
getId()
    {
        return
$this->_id;
    }
}

class
B
{
    private static
$_instance;

    public static function
singleton()
    {
        if (!isset(
self::$_instance)) {
           
self::$instance = new A();
        }
        return
self::$instance;
    }
}

?>
Here class B act as a guard to class A. But as same as the first section, it's useless too! Unless you can make sure that the users of your class will never find the class A, you shouldn't make the class you wanna to be unique can be instantiated many times.

So the best way to create a unique instance of a class is that the class save the unique instance itself. It is the core meaning of singleton pattern. Any information that mentioned here can be found in the book of GoF. I think it's worth reading the book.

BTW: It's allowed that there are a few of subclasses of a singleton class.
contact_us at haltebis dot com
18-Mar-2006 06:27
Here is my PHP5 Singleton only ("no getInstances()")

<?php
#file class.singleton.php
class singleton
{
   var
$instance;

   function
__construct()
   {
      static
$instances=array();
     
$class = get_class($this);
      if(!isset(
$instances[$class])) $instances[$class] = $this;
      foreach(
get_class_vars($class) as $var => $value)
      {
        
$this->$var = &$instances[$class]->$var;
      }
     
$this->instance = &$instances[$class];
   }

   function
__set($name,$value)
   {
      
$this->$name = $value;
       if(!isset(
$this->instance->$name)) $this->instance->$name = &$this->$name;
   }

}
?>

And here is the SimpleTest unit that I use

<?php
#file test.singleton.php

class singleton_example extends singleton
{
   var
$x;
   var
$y;

   function
__construct()
   {
     
parent::__construct();
   }
}

class
singleton_example2 extends singleton
{
   var
$x;
   var
$y;

   function
__construct()
   {
     
parent::__construct();
   }
}

class
TestOfSingleton extends UnitTestCase
{
   function
TestOfSingleton()
   {
     
$this->UnitTestCase();
   }

   function
testSet_and_Get1()
   {
     
$test1 = new singleton_example();