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.

例 19-25. 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.

例 19-26. 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;

?>

add a note add a note User Contributed Notes
alexandre at ONLY-HAM-NOT-SPAM dot gaigalas dot net
22-Jul-2007 01:01
A minimalistic singleton implementation I create for my new framework

<?php
class foo
{
   static private
$i;
   private function
__construct()
   {
       echo
"I'm alive";
   }
   static public function
singleton()
   {
       return ((isset(
self::$i) || $n = __CLASS__) && self::$i = new $n) ? self::$i : NULL;
   }
}
?>
anonymous at world4ch dot org
16-Jul-2007 08: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 10: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 10: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 10: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 08: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 05: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
30-Sep-2006 12: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 07: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 07: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 04: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 08: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.
07-May-2006 05:55
I have founded an additional way to use singleton, which made the __CLASS__ define in this function unneeded. Just by using new self; Im not sure if this is reducing the parsetime.
<?php

class Example {
   private static
$instance;

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

       return
self::$instance;
   }

   public function
printString() {
       return
"I need to be printed.";
   }
}

$foo = Example::getInstance();
print
$foo->printString();

?>
lycboy at gmail dot com
29-Apr-2006 10: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
19-Mar-2006 02: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();
    
$test1->x = 'a';;
    
$test1->y = 'b';

    
$test2 = new singleton_example();
    
$test2->x = 'c';
    
$test2->y = 'd';
    
$test2->z = 'e';

    
$test3 = new singleton_example2();

    
$this->assertEqual($test1->x,'c');
    
$this->assertEqual($test1->y,'d');
    
$this->assertEqual($test1->z,'e');

    
$this->assertEqual($test3->x,null);
    
$this->assertEqual($test3->y,null);
   }
}
?>

Never failed me until now
jphp at dsf dot org dot uk
05-Feb-2006 10:36
Aya:

Yes, the example as it stands is pretty useless, and a static method achieves the same result much more easily.  But with a more complicated system, say you have two different ways of doing "bark":

<?php
  
class Example1 {
    
// singleton implementation boilerplate goes here
    
public function bark() { echo "Woof"; }
   }

   class
Example2 {
    
// singleton implementation boilerplate goes here
    
public function bark() { echo "Yap"; }
   }

  if (
/* some condition */)
  
$method = Example1::singleton();
  else
  
$method = Example2::singleton();

  for (
$i = 0; $i < 10; $i++) $method->bark();
?>
vsviridov at exceede dot com
30-Jan-2006 04:39
Singleton is a very useful pattern if you need multiple instances of different classes to use only one unique instance of common class. It's not just about having static methods.

e.g. Your database connection class probably should be a singleton, in order to spare all redundant connect calls, etc...
aya at eh dot org
01-Dec-2005 11:05
Personally I find the aforementioned 'singleton pattern' pointless in many cases, since a class containing only static members and functions is already a 'singleton'. The code in 'Example 19-25' above could simply read:

<?php

  
class Example
  
{
      
// Example method
      
public static function bark()
       {
           echo
'Woof!';
       }
   }

  
// Call 'singleton' method
  
Example::bark();

?>
toomuchphp-phpman at yahoo dot com
27-Nov-2005 01:46
The principle of the Singleton pattern can easily be expanded to form [what I have dubbed as] the 'Unique' pattern - where a particular class may have several instances, each with a 'Unique ID'.  This can be useful when a single instance is required for each database record.

<?php

 
// Each instance of 'Customer' represents one customer!
 
class Customer {

    
// Access a unique instance of class for a customer record
    
public function Unique($CustomerID) {
       static
$instances = array();

      
// a unique instance for each CustomerID
      
if(!isset($instances[$CustomerID]))
        
$instances[$CustomerID] = new Customer($CustomerID);

       return
$instances[$CustomerID];
     }

     private
$CustomerID;

     private function
__construct($CustomerID) {
      
$this->CustomerID = $CustomerID;
     }
  }

 
// get instance of class for customer #1
 
$C1 = Customer::Unique(1);

 
// get instance of class for customer #2
 
$C2 = Customer::Unique(2);

?>
peetersdiet at gmail dot com
01-Nov-2005 01:02
As i reread my previous post i noticed 1 minor error. Namely that it is best to declare the singletonFactory()-method protected if u don't need to be able to use the method publicly. This way the implementation incorporates even better encapsulation.
peetersdiet at gmail dot com
31-Oct-2005 03:57
@ steffen at morkland dot com:

Interesting problem and u are right about always having to put the non-public constructor and public singleton-method in the classes that need to be singletons. U are also right about an interface not being able to declare a constructor private or protected.

Why not store all singletons in a static variable of a common parent class and make singleton-capability available to all childclasses? We can accomplish this by adding a hybrid singletonFactory()-method in that parent class and make the constructor of the childclass protected to enforce the singleton-pattern. At this moment all childclasses can be a singleton! Not to robust.

U can have childclasses implement the Singleton-interface as specified in ur post so classes can be tested on implementing this interface. If u always implement the interface on ur singleton-classes u can add a test to the singletonFactory()-method to check whether the class u are about to instantiate does implement the Singleton-interface. Together with the enforced prototyping of the singleton()-method this provides a more foolproof usage of the singleton-pattern.

The singleton code is implemented in the parent so no rewriting of the code is necessary, thus avoiding programmer mistakes in the childclasses and keeping the code cleaner to the eye. The only methods the childclass needs are a protected constructor to avoid direct instantiation and a wrapping singleton()-method.

<?php
// As stated by steffen we can't restrict visibility of the constructor in an interface
interface Singleton {
   public static function
singleton();
}

// Parent class:
// U can define these methods at the highest level so the singleton-functionality
// is available to all objects, but it works at all levels of an object hierarchy.
class ParentClass {
   private static
$childSingletons = array();  // store singletons for each childclass
  
  
public static function singletonFactory($class='')
   {
       if (!isset(
self::$childSingletons[$class])) {  // singleton not loaded?
          
if (include_once($class.'.php')) {  // classfile included?
              
$thisClass = __CLASS__;
              
$object = new $class;
               if (
$object instanceof $thisClass) { // class is childclass? (so we can access the protected constructor)
                  
$classImplements = class_implements($object);
                   if (isset(
$classImplements['Singleton'])) {  // class implements Singleton?
                      
self::$childSingletons[$class] = new $class;
                   } else {
                       throw new
Exception ('Class \''.$class.'\' does not implement interface Singleton');
                   }
               } else {
                   throw new
Exception ('Unknown class \''.$class.'\'');
               }
           } else {
               throw new
Exception ('Class \''.$class.'\' not found');
           }
       }
       return
self::$childSingletons[$class];
   }
}

// Child class:
// 1. Define the constructor as protected.
// 2. Implement interface Singleton ...
//      ... to enforce prototype of singleton()
//      ... to be able to dynamically identify the class as a singleton.
// 3. Define the singleton()-method acting as a wrapper for the parent's singletonFactory()-method.
class ChildClass extends ParentClass implements Singleton{
   protected function
__construct() {}
  
   public static function
singleton() {
       return
parent::singletonFactory(__CLASS__);
   }
}

// public usage
$singleton = ChildClass::singleton();
?>

If u prefer more loose programming u can leave the Singleton interface out of the picture alltogether and create your childsingletons directly with the singletonFactory()-method. This approach only needs the protected constructor(), no singleton()-method. I know this approach allows all the childclasses to be treated as singletons. In my opinion this is not a problem, but the lack of robustness and absence of dynamic testability is. ;)
steffen at morkland dot com
11-Oct-2005 02:47
Regarding the singleton pattern, you have to create the function for every singleton class you want to have, because settting a variable static will set the variable on all instances of the class, and second of all, by extending a singleton class, you are breaking rule No #1 of the singleton pattern. an instance of a given type may only excist ONCE, by extending the singleton class you have multiple instances of the singleton class, and by is sharing the static $instance variable.

on thing could be done though, to make sure a programmer does not make any mistakes when creating singleton classes, an interface could be made, to make sure the singleton class is correctly defined.

it could look something like this:

<?php
interface singleton {
   public static function
getInstance();
}
?>

however, this interface does NOT force the programmer to make the constructor private, and don't even bother to try, it would just result in a error.

sorry to say it guys, there are no easy way around this one. not even a factory class can do the job for you since, the constructor must be private, to ensure that only one instance excists.
axon dot wp a at t wp dot pl
05-Oct-2005 04:25
Short version of Singleton:
<?php
public function __clone()
   {
      
trigger_error('Clone is not allowed.', E_USER_ERROR);
   }
?>
   
is :
<?php private function __clone() {} ?>
rashkatsa
30-Sep-2005 12:03
Hi there,

As Singleton patterns are used for years in Java, today we tend toward overriding 'new' operator (as singleton returns always the same instance for every 'new' that you call...). In order to do this, we use IoC (http://www.martinfowler.com/articles/injection.html). With lightweight container, you delegate the 'new' to a specific factory which decides if it has to return a new instance on each call or always the same instance. You homogenize your code as you don't have "new MyClass()" and "MyClass2::getInstance()" but always the same call : Component::get(MyClass) and Component::get(MyClass2). [PHP implementation hint : You can choose the parameter of the get method : class, classname, ...]. It's the component which decides if it has to return a new instance or not.

If you take a look at Java Spring framework (which use getBean(Class) method) or PicoContainer (which use getComponentInstance(Class) method - see 2 minutes tutorial on their site), you can configure the behavior for your class in an XML file (choosing that ClassA is a singleton and ClassB is not). With this configuration, you don't need to pollute your class code with _instance field but you just create a standard class (non invasive pattern).

when you would have a PHP generic component (class) factory, you can go further and build a complete PHP IoC (if it not already exists :)) and then the component factory injects dependencies itself (choose through constructors or mutators).

regards,

rashkatsa.
lukas dot starecek at centrum dot cz
17-Jul-2005 08:12
If you need singleton of any class and don't want write singleton wrapper for each this class, try this:

class UniverzalSingleton {

   const EXCEPTION_NO_CLASS = 1;

   protected static $_instances = array();

   public static function getInstance($class) {
       if (!isset(self::$_instances[$class])) {
           if (!class_exists($class))
               throw (new Exception(__CLASS__ . ': Requsted class is not exist.', self::EXCEPTION_NO_CLASS));
           self::$_instances[$class] = new $class();
       } // if
       return self::$_instances[$class];
   } // getInstance

} // class UniverzalSingleton
disappear dot nz at gmail dot com
08-Jul-2005 06:57
Hi ,

Singleton Patterns are excellent ,
I have created a singleton pattern that enables any class to be loaded from the one modular singleton library.

<?php

  
class singleton
  
{
       private static
$o_instance = NULL ;

       public static function
call_singleton ( $s_class )
       {
           if (
class_exists ( $s_class ) )
           {
               if (
self :: $o_instance === NULL )
               {
                  
self :: $o_instance = new $s_class ;
               }
           }           
           return
self :: $o_instance ;
       }
   }

?>
php at mijav dot dk
07-Jul-2005 04:46
Please use design patterns as they were intended:

Design patterns are designs that are known to solve common problems, such as having only 1 instance of a class. Design patterns are are not code libraries.
Most design patterns, if not all, have alternate implementations but common to them all is that the recommended implementation solves the problem.

Singleton should not be made as a class and then extended. Nor shuld __autoload be used.
Autoloading is very PHP-specific (and there might be nothing wrong with that, but design patterns are general patterns that are abstracted from the implementing language).
Making a class that you extend is very ugly. What if you have to extend that class too? You will have to make a dummy that extends your singleton class, just so you can extend the class you want. This is a very "ugly" solution that completely overrules the idea of well known design patters: A thought-though idea that works the way intended.

The manual shows a PHP implementation of the standard Singleton-pattern without "nifty" modifications.

To finish off this lesson on design patterns, I would like to ackknowledge that there is nothing wrong in tweaking patterns to suit your needs.
But remember: "If it isn't broken - don't fix it".
03-Jul-2005 06:28
Here's an effective strategy for creating singletons.

1.) define an __autoload() function

2.) Define all properties of a class to be static

3.) Make the constructor private.

Now, anywhere in your code, you can simply do as follows:

Class::Function();

The __autoload() function will take care of loading the class.

It's even better when you use the auto_prepend directive to define __autoload(). Now you can create a php script which looks like this:

<?php
TemplateSystem
::Start();
echo
'This is just a test!';
TemplateSystem::Stop();
?>

Now you've effectively got a 2-line solution to all templating issues, the templates will be available to every script, and the only additional overhead that you'll have for scripts that don't use the templating system is a 3-line autoload function!

Obviously, there's still a problem with __autoload() if you are attempting to write a templating system that has to work with someone else's software that also defines __autoload(). The best advice I can give here is to remove one of the __autoload()'s and modify the other to work with both.
traxer ad gmx.net
02-Jun-2005 10:29
In response to Richard Quadling's response to Scott Mattock's response to Jimmy Paterson ...

The singleton pattern is a /pattern/, not a class. There is no way to move the whole functionality of 'being a singleton' into a common base class, it was not intended that way. There is no point in adding features to derived classes, other than for internal use, either. Furthermore, when I derive two classes from Singleton, the singleton is not really a singleton anymore. Considering this, I think your implementation of Singleton and SubClass (i.e your correction to Scott Mattock's) is the one that most closely matches the intention of GOF. You can allow sublasses of SubClass, though:

<?php
class Singleton {
   private static
$instance;
   public static function
singleton($class = __CLASS__) {
       if (!isset(
self::$instance))
          
self::$instance = new $classname;
       return
self::$instance;
   }
}
class
SubClass extends Singleton {
   public static function
singleton($class = __CLASS__) {
       return
parent::singleton($class);
   }
}
class
SubSubClass extends SubClass {
   public static function
singleton($class = __CLASS__) {
       return
parent::singleton($class);
   }
}
?>

This even works with php4 if you
1. move the Singleton::$instance into function Singleton::singleton,
2. get rid of the unsuported keywords and
3. rename the Singleton::singleton method (so as not to be a constructor).
So no real imporvement here, except for the added protection of not beeing able to create objects explicitly.
anon at anon dot org
23-May-2005 08:02
After programming a number of real world applications with PHP, I found that this version of the singleton doesn't really resemble other singleton patterns, but is the only one I've ended up using and it works great.

<?php

class User {
  
/* .. your code, nothing specific matters in the class .. */
}

function
user(){
   static
$user;
   if(!isset(
$user))
      
$user = new User();
   return
$user;
}

//creates the user object then calls a method on it
user()->doSomething();

//calls a method on the same object
user()->doSomethingElse();

?>

Note that it is *possible* to create multiple instances of User, but in your API docs, or when you tell people how to use the class just say you are supposed to refer to it only via the user() function, and then there should be no reason to enforce it in your code any other way.

Also note that this syntax is only possible in PHP 5 because of the object / function dereferencing feature.  user()->someMethod(); will throw a fatal error in 4.x
dmnEe0 at gmail dot com
14-May-2005 09:13
I struggled a few hours on writing a simple Generic factory method for dynamic object factoring. I initially went for call_user_func_array() to create the object but that obviously didn't work. An anonymous function was what I needed. Here's the result (PHP5):

<?php
/**
 *    Name:    Factory
 *    Author:    Ezku
 *    Contact:    dmnEe0 at gmail dot com
 */
class Factory
{
  
/**
     * Generic factory method
     * @param string    Path to class definition
     * @param string    Basic class name
     * @param string    Derived class name
     * @param array    Class constructor arguments, optional
     */
  
public static function Generic($filename, $base, $derived, $args = array())
   {
      
/**
         * Check that the file exists
         */
      
if(file_exists($filename))
       {
           include_once
$filename;
          
/**
             * Check that the file contained the appropriate class definition
             */
          
if(class_exists($derived))
           {
              
/**
                 * Create argument list for constructor
                 */
              
$arglist = array();
               for(
$i = 0, $n = count($args); $i < $n; $i++)
                  
$arglist[] = '$args['.$i.']';
              
$arglist = implode(',',$arglist);
              
              
/**
                 * Create new instance via an anonymous function
                 */
              
$new_class = create_function('$name, $args', 'return new $name('.$arglist.');');
               return
$new_class($derived, $args);
           }
           else
               throw new
Exception("Definition file ($filename) did not contain definition for the $base class <code>$derived</code>");
       }
       else
           throw new
Exception("Definition file ($filename) for the $base class <code>$derived</code> was not found");
   }
}

/**
 * Useless usage example:
 */
function createCat($name, $scary_eyes = FALSE, $whiskers = TRUE)
{
  
$path = PATH_ANIMALS.'/'.$name.'.php';
  
$base = 'Cat';
  
$derived = $name.$base;
  
$args = array($scary_eyes, $whiskers);
   return
Factory::Generic($path, $base, $derived, $args