类与对象
在线手册:中文 英文
PHP手册

设计模式

使用设计模式是促进最佳实践和良好设计的好办法。设计模式可以提供针对常见的编程问题的灵活的解决方案。

工厂模式

工厂模式(Factory)允许你在代码执行时实例化对象。它之所以被称为工厂模式是因为它负责“生产”对象。工厂方法的参数是 你要生成的对象对应的类名称。

Example #1 调用工厂方法(带参数)

<?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');
        }
    }
}
?>

按上面的方式可以动态加载drivers。如果Example类是一个数据库抽象类,那么 可以这样来生成MySQLSQLite驱动对象:

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

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

单例

单例模式(Singleton)用于为一个类生成一个唯一的对象。最常用的地方是数据库连接。 使用单例模式生成一个对象后,该对象可以被其它众多对象所使用。

Example #2 单例模式

<?php
class Example
{
    
// 保存类实例在此属性中
    
private static $instance;
    
       
// 构造方法声明为private,防止直接创建对象
    
private function __construct() 
    {
        echo 
'I am constructed';
    }

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

        return 
self::$instance;
    }
    
    
// Example类中的普通方法
    
public function bark()
    {
        echo 
'Woof!';
    }

    
// 阻止用户复制对象实例
    
public function __clone()
    {
        
trigger_error('Clone is not allowed.'E_USER_ERROR);
    }

}

?>

这样我们可以得到一个独一无二的Example类的对象。

<?php

// 这个写法会出错,因为构造方法被声明为private
$test = new Example;

// 下面将得到Example类的单例对象
$test Example::singleton();
$test->bark();

// 复制对象将导致一个E_USER_ERROR.
$test_clone = clone $test;

?>

类与对象
在线手册:中文 英文
PHP手册
PHP手册 - N: 设计模式

用户评论:

geliscan[at]gmail[dot]com (03-Dec-2011 11:05)

This is a simple Command Pattern example which performs Undo operation on a calculator. You may use callbacks in order to verify open-close principle.
<?php
abstract class Command {
    abstract public function
unExecute ();
    abstract public function
Execute ();
}
class
concreteCommand extends Command {
    private
$operator,$operand,$calculator;
    public function
__construct ($calculator,$operator,$operand) {
       
$this->operator = $operator;
       
$this->operand = $operand;
       
$this->calculator = $calculator;
    }
    public function
Execute() {
       
$this->calculator->Action($this->operator,$this->operand);
    }
    public function
unExecute () {
       
$this->calculator->Action($this->Undo($this->operator),$this->operand);
    }
    private function
Undo ($operator) {
        switch (
$operator) {
            case
'+': return '-';
            case
'-': return '+';
            case
'*': return '/';
            case
'/': return '*';
        }
    }
}
class
Calculator {
    private
$current;
    public function
__construct() {
       
$this->current = 0;
    }
    public function
Action($operator,$operand) {
        switch (
$operator) {
            case
'+':
               
$this->current += $operand;
                break;
            case
'-':
               
$this->current -= $operand;
                break;
            case
'*':
               
$this->current *= $operand;
                break;
            case
'/':
               
$this->current /= $operand;
                break;
        }
    }
    public function
getCurrent() {
        return
$this->current;
    }
}
class
Invoker {
    private
$commands,$calculator,$current;
    public function
__construct() {
       
$current =-1;
    }
    public function
Undo() {
        if (
$this->current >= 0) {
           
$this->commands[$this->current]->unExecute();
           
$this->current--;
        }
    }
    public function
Compute($command) {
       
$command->Execute();
       
$this->current++;
       
$this->commands[$this->current] = $command;
    }
}

?>

Example Usage:

<?php
$User
= new Invoker();
$calculator = new Calculator();
$command = new concreteCommand($calculator,'+',5);
$User->Compute($command);
echo
"After +5: ".$calculator->getCurrent()."<br/>";
$command = new concreteCommand($calculator,'*',7);
$User->Compute($command);
echo
"After *7: ".$calculator->getCurrent()."<br/>";
$command = new concreteCommand($calculator,'/',2);
$User->Compute($command);
echo
"After /2: ".$calculator->getCurrent()."<br/>";
$command = new concreteCommand($calculator,'-',10);
$User->Compute($command);
echo
"After -10: ".$calculator->getCurrent()."<br/>";
$User->Undo();
echo
"Undo Operation: ".$calculator->getCurrent()."<br/>";
$User->Undo();
echo
"Undo Operation: ".$calculator->getCurrent()."<br/>";
$User->Undo();
echo
"Undo Operation: ".$calculator->getCurrent()."<br/>";
$User->Undo();
echo
"Undo Operation: ".$calculator->getCurrent()."<br/>";
?>

and Output:

After +5: 5
After *7: 35
After /2: 17.5
After -10: 7.5
Undo Operation: 17.5
Undo Operation: 35
Undo Operation: 5
Undo Operation: 0

patrick at bierans dot de (24-Feb-2011 06:42)

It is possible to use every class
as if it is a singleton with a little abstraction.

I wrote some code to show you:

<?php
 
class MyEngine{ /* static */
   
static $singletons=array();
    static function
singletonizer($classname,$classarguments=array()){
     
$sca=serialize($classarguments);
      if (!isset(
MyEngine::$singletons[$classname][$sca])) {
        if (!
class_exists($classname))
         
/* auto loader, add error reporting for missing classes etc */
         
include("classes/".$classname."/.class.php");
       
MyEngine::$singletons[$classname][$sca]
          =& new
$classname($classarguments);
      }
     
/* this is the pointer/reference and not a new object! */
     
return MyEngine::$singletons[$classname][serialize($classarguments)];
    }
    static function
debug($msg,$data=""){
      echo
"<pre>".$msg."\t".print_r($data,1)."</pre>\r\n";
    }
  }
?>  

Now let's test it!
Defining a class:

<?php
 
class testclass{
    private
$value;
    function
__construct($args){
     
MyEngine::debug("- testclass contructed with ",$args);
      if (isset(
$args["value"]))
       
$this->set($args["value"]);
      else
       
$this->value=0;
    }
    public function
set($value){
     
$this->value = $value;
     
MyEngine::debug("- testclass set value =",$this->value);
    }
    public function
get(){
     
MyEngine::debug("- testclass get value =",$this->value);
      return
$this->value;
    }
  }
?>

And here we run a testcase:

<?php
  $args
=array("value"=>12);
 
MyEngine::debug('create $a','expecting: contruct and set 12');
 
$a=MyEngine::singletonizer("testclass",$args);
 
$a->set(13);
 
MyEngine::debug('create $b','expecting: just load it. should be 13, no contruct');
 
$b=MyEngine::singletonizer("testclass",$args);
 
MyEngine::debug("b value is (expecting 13)",$b->get());
 
$args=array("value"=>11);
 
MyEngine::debug('create $c','different args -> new construct, set 11');
 
$c=MyEngine::singletonizer("testclass",$args);
 
MyEngine::debug("c value is (expecting 11)",$c->get());
 
$args=array("value"=>12);
 
MyEngine::debug('create $d','recognize args, load it, should be 13');
 
$d=MyEngine::singletonizer("testclass",$args);
 
MyEngine::debug("d value is (expecting 13)",$d->get());
?>

feedback welcome!

HTH :)

Patrick from Berlin, Germany

sjh (21-Jan-2011 02:27)

The problem with the singleton pattern is that there aren't really many cases where it is a true singleton.

There are many cases where you want to get access to a specific object that is the same each time.
For example accessing objects that have different drivers.

In this instance its better to use the Lazy Initialization pattern:

<?php
abstract function Lazy_Initialization_Object {
   
/* Set up the array of instances */
   
protected static $instances = array();

   
/** Make sure the constructor isn't accessible to
     * the rest of the world
     */
   
private function __construct() {}

   
/**
     * Returns a specific object that relies on the
     * parameter passed
     *
     * @param string class name to be returned
     * @throws Exception if $type doesn't extend __CLASS__
     */
   
public function get_object($type) {
       
$reflection_class = new ReflectionClass($type);

       
// Check if the object is a Lazy Iinitialization Object
       
if( ! $reflection_class->isSubclassOf(__CLASS__))
            throw
Exception("$type does not extend __CLASS__");

       
// Check if the object already exists in the pool
       
if( ! array_key_exists($type,self::$instances)) {
         
// If not initialise a new one and place it in the pool
           
self::$instances[$type]=$reflection_class->newInstance();
        }

       
// Return the object you want
       
return self::$instances[$type]   

    }

   
/** Specify all the functions that these drivers have in common */
   
public abstract function initialize($name);

    public function
display() {

       echo
$content
   
}

    protected
$content;
}

class
Person_Driver_HTML extends Lazy_Initialization_Object {
   
   public function
initialize($name) {
        
$content = "<p>Name: $name</p>";
   }

}

class
Person_Driver_Raw extends Lazy_Initialization_Object {
    public function
initialize($name) {
        
$content = "name: $name";
    }

}

Lazy_Initialization_Object::
   
get_object("Person_Driver_Raw")->initialize("fifi");

Lazy_Initialization_Object::
   
get_object("Person_Driver_HTML")->initialize("fifi");

Lazy_Initialization_Object::
   
get_object("Person_Driver_HTML")->display();
// will output "<p>Name: fifi</p>"
Lazy_Initialization_Object::
   
get_object("Person_Driver_Raw")->display();
// will output "name: fifi";

echo Lazy_Initialization_Object::
        
get_object("Person_Driver_HTML") ===
    
Lazy_Initialization_Object::
        
get_object("Person_Driver_HTML"); // TRUE

echo Lazy_Initialization_Object::
        
get_object("Person_Driver_HTML") ===
    
Lazy_Initialization_Object::
        
get_object("Person_Driver_Raw"); // FALSE

?>

boukeversteegh at gmail dot com (18-Aug-2010 10:05)

I've come up with an interesting and intuitive way to define a generic Factory class. It's basically an empty object that remembers all operations you perform on it. You can then request an actual instance, and all operations are repeated on that instance. The order of the operations is preserved.

<?php
   
# If you want a factory that initializes an object like this:
   
$myobject = new MyObject('arg1', 'arg2');
   
$myobject->doFooBar();
   
$myobject->baz = 10;
   
   
# You write:
   
$f_myobject = new MagicFactory('MyObject', 'arg1', 'arg2');
   
$f_myobject->doFooBar();
   
$f_myobject->baz = 10;

   
# You can now get the same object like this:
   
$myobject = $f_myobject->instance();
?>

<?php
   
   
/**
     * Generic Factory class
     *
     * This Magic Factory will remember all operations you perform on it,
     * and apply them to the object it instantiates.
     *
     */
   
class MagicFactory {
        private
$history, $class, $constructor_args;
       
       
/**
         * Create a factory of given class. Accepts extra arguments to be passed to
         * class constructor.
         */
       
function __construct( $class ) {
           
$args = func_get_args();
           
$this->class = $class;
           
$this->constructor_args = array_slice( $args, 1 );
        }
       
        function
__call( $method, $args ) {
           
$this->history[] = Array(
               
'action'    => 'call',
               
'method'    => $method,
               
'args'        => $args
           
);
        }
       
        function
__set( $property, $value ) {
           
$this->history[] = Array(
               
'action'    => 'set',
               
'property'    => $property,
               
'value'        => $value
           
);
        }
       
       
/**
         * Creates an instance and performs all operations that were done on this MagicFactory
         */
       
function instance() {
           
# use Reflection to create a new instance, using the $args
           
$reflection_object = new ReflectionClass( $this->class );
           
$object = $reflection_object->newInstanceArgs( $this->constructor_args );
           
           
# Alternative method that doesn't use ReflectionClass, but doesn't support variable
            # number of constructor parameters.
            //$object = new $this->class();
           
            # Repeat all remembered operations, apply to new object.
           
foreach( $this->history as $item ) {
                if(
$item['action'] == 'call' ) {
                   
call_user_func_array( Array( $object, $item['method'] ), $item['args'] );
                }
                if(
$item['action'] == 'set' ) {
                   
$object->{$item['property']} = $item['value'];
                }
            }
           
           
# Done
           
return $object;
        }
    }
   
?>

Example:

<?php
   
   
class Person {
        private
$name, $sirname;
        public
$age;
       
        function
__construct( $name, $sirname ) {
           
$this->name = $name;
           
$this->sirname = $sirname;
        }
       
        function
setName( $name ) {
           
$this->name = $name;
        }
       
        function
introduce() {
            print
"Hello, my name is {$this->name} {$this->sirname}! I'm {$this->age} years old.";
        }
    }
   
   
# Setup a factory
   
$person_factory = new MagicFactory('Person', 'John', 'Johnson');
   
$person_factory->setName('Jack');
   
$person_factory->age = 55;
   
   
# Get an instance
   
$jack = $person_factory->instance();
   
$jack->introduce();
   
   
# Prints:
    # Hello, my name is Jack Johnson! I'm 55 years old

Anonymous (10-Jun-2010 01:39)

Singleton in php doesn't responded like java (or others), the static instance resets on every request......

Deman (05-Mar-2010 03:11)

Php needs macros! That's right php seems almost unusable sometimes without precompiler. Fortunately you can generate php code with php and (easily) cache it so you can still take advantage of the php optimizing capabilities. It just creates a mess when debugging, no big deal ;)

You need to extend the language to your own needs.

But this singleton business might just work without without macros, not that nicely though.

<?php
class Singleton {
    private static
$instance;
    public static function
singleton($class = __CLASS__) {
        if (!isset(
self::$instance))
           
self::$instance = array();
        if (!isset(
self::$instance[$classname]))
           
self::$instance[$classname] = new $classname;
        return
self::$instance[$classname];
    }
}
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);
    }
}
?>

As you can see, the static $instance can be an associative array holding all the instances of derived classes, but you still can't work around overriding the singleton/getInstance static method... That's what macros or language extensions would be for...

<?php
class SINGLETON(SubClass) {
   
/*...*/
}
?>

Translate to:

<?php
class SubClass extends Singleton {
    public static function
singleton($class = __CLASS__) {
        return
parent::singleton($class);
    }
   
/*...*/
}
?>

quentinberlemont at gmail dot com (17-Dec-2009 05:01)

<?php
/**
 * Class Singleton is a generic implementation of the singleton design pattern.
 *
 * Extending this class allows to make a single instance easily accessible by
 * many other objects.
 *
 * @author     Quentin Berlemont <quentinberlemont@gmail.com>
 */
abstract class Singleton
{
   
/**
     * Prevents direct creation of object.
     *
     * @param  void
     * @return void
     */
   
protected function __construct() {}

   
/**
     * Prevents to clone the instance.
     *
     * @param  void
     * @return void
     */
   
final private function __clone() {}

   
/**
     * Gets a single instance of the class the static method is called in.
     *
     * See the {@link http://php.net/lsb Late Static Bindings} feature for more
     * information.
     *
     * @param  void
     * @return object Returns a single instance of the class.
     */
   
final static public function getInstance()
    {
        static
$instance = null;

        return
$instance ?: $instance = new static;
    }
}
?>

E.g.

<?php
// Foo class
class Foo extends \Framework\Core\Singleton
{
   
// Bar method
   
public function bar()
    {
        echo
__CLASS__ . PHP_EOL;
    }
}

// Returns a single instance of Foo class
$foo = Foo::getInstance();

// Prints: Foo
 
$foo->bar();
?>

Best regards,
Quentin.

ltearno at gmail dot com (22-Sep-2009 05:11)

The Singleton class version wich is useable by only extending it :

you would use is for example like this :

<?php
class Users extends Singleton
{
   
// ...
   
public function SomeMethod()
    {
    }
}
?>

and in your code :

<?php
Users
::inst()->SomeMethod();
?>

I didn't check for performance, but here is the code :

<?php
class Singleton
{
   
// Hold an instance of the class
   
private static $instances = array();
   
   
// A private constructor; prevents direct creation of object
   
final private function __construct()
    {
    }

   
// Prevent users to clone the instance
   
final public function __clone()
    {
       
trigger_error( 'Clone is not allowed.', E_USER_ERROR );
    }
   
   
// The singleton method
   
final public static function inst()
    {
       
$c = get_called_class();
       
        if( ! isset(
self::$instances[$c] ) )
        {
           
self::$instances[$c] = new $c;
        }
       
        return
self::$instances[$c];
    }
}
?>

edgar at goodforall dot eu (25-Aug-2009 10:03)

Example, which shows how the class works:
<?php

/* First we create hunderd numbered chainable classes, which will quadrate the passed integer if the number of the class is the same as the integer.
*/
for($i = 0; $i < 100; $i++){
$funcs[] = create_function('','class C'.$i.' extends Chainable {
        public function run(Message $msg){

        $int = $msg->getMessage();
        if($int == '
.$i.'){
                return new Message($int * $int);

        }

        }
        };
        return new C'
.$i.';

        '
);
}
/* Then we create a function, which will chain the objects together and returns C0.
 C0 -> C1 -> C2 -> C3 ... -> C99
*/
function chain($funcs, $c = null){
        if(
$c == null){
               
$func = array_pop($funcs);
               
$c = $func();
               
$init = true;
        } else {
               
$init = false;
        }
        if(
count($funcs) > 0){
               
$func = array_pop($funcs);
               
$d = $func();
               
$c->addLink($d);
               
chain($funcs, $d);
        }
        if(
$init){
                return
$c;
        }
}
/* Create the chain */
$c = chain($funcs);

/* Now we can use the chain to calculate quadrates up to 99
output:
25
No object can handle this type
*/
try {
/* This will forward the new Message(5) to C0 then to C1 until it reaches C5,
which calculates 5 * 5 and then returns new Message(5 * 5) to C4 -> C3 .. ->C0 -> caller
When I enter 100 the chain will fail to process the integer, because there is no C100 class. C99 will throw an exception.
*/ 
       
$mesg = $c->forward(new Message(5)); // 25
       
print $mesg . "\n";
       
$mesg = $c->forward(new Message(100));
        print
$mesg . "\n";
} catch(
Exception $e) {
        print
$e->getMessage() . "\n";
}
?>

edgar at goodforall dot eu (24-Aug-2009 05:39)

This class will let you chain objects together into a chain. You can forward a message into the chain. The message propagates upwards into the chain until an object can handle it and returns a value. Then the return value is send backwards into the chain until it reached the caller.

This can be useful in various situations, where flexibility is needed.

In the begin of the chain we put more specialized methods, which will handle special cases (like user defined objects, json code, xml etcetera). And in the back more general (strings, array's). Now we can pass data to the chain and always get valid and safe html back. If we encounter a new data type we just put on the head of the chain a new object, which can handle this type of data.

<?php

abstract class Chainable {
        protected
$next = null;
        protected
$prev = null;
        protected
$res = null;

        public function
forward(Message $object){
                if(
$return = $this->run($object)){
                        return
$this->backward($return);
                }
                if(
$this->next !== null){
                        return
$this->next->forward($object);
                } else {
                        throw new
Exception('No object can handle this type');
                }
        }
        public function
backward(Message $object){
        
                if(
$this->prev === null){
                        return
$object;
                } else {
                        return
$this->prev->backward($object);
                }
        }
        abstract public function
run(Message $object);
        public function
addLink(Chainable $link){
                if(
$this->next !== null){
                       
$this->next->addLink($link);
                } else {
                       
$this->next = $link;
                       
$this->next->setPrevLink($this);
                }
                return
$this;
        }
        protected function
setPrevLink(Chainable $link){
               
$this->prev = $link;
                return
$this;
        }
}
?>

Also needed the message object:

<?php
   
class Message {
        protected
$data;
        public function
__construct($data){
               
$this->data = $data;
        }
        public function
getMessage(){
                return
$this->data;
        }
        public function
setMessage($data){
               
$this->data = $data;
        }
        public function
__toString(){
                return (string)
$this->data;
        }
}

?>

edgar at goodforall dot eu (13-Jul-2009 04:48)

Example of a decorator, which adds array access to any object:

<?php

class ArrayAccessDecorator implements ArrayAccess {
        protected
$object = null;
        public function
__construct($object){
               
$this->object = $object;
        }
        public function
__call($method, $args){
                return
$this->productpart->$method($args);
        }
        public function
__set($key, $val){
               
$this->object->$key = $val;
        }
        public function
__get($key){
                return
$this->object->$key;
        }
       
/* ArrayAccess */
       
public function offsetSet($key, $value){
               
$this->__set($key, $value);
        }
        public function
offsetGet($key){
                return
$this->__get($key);
        }
        public function
offsetUnset($key){
               
$this->__set($key, null);
        }
        public function
offsetExists($offset){

                       
$test = $this->object->__get($offset);
                        if(
$test !== null){
                                return
true;
                        } else {
                                return
false;
                        }
        }
}

$stdobject = (object)array('test'=>'test', 'test2' => 'test2');
$arr = new ArrayAccessDecorator($stdobject);
print
$arr['test']; // test
$arr['test'] = 'hello';
print
$arr['test']; // hello
?>

rskret at gmail dot com (04-Jun-2009 11:46)

Ex.2 only makes a 'Singleton' in the sense there is only one object makable.
But! you can still assign the object to other names(like making aliases). Probably not
what you usually want. Change the method a bit and you get only one unique name
for your 'Singleton'.. or else it will bark again and again!
<?php
#if you don't change example 2 you will get a $badDoggie
$badDoggie="I am constructedSorry but I'm already set.Sorry but I'm already set.
            Sorry but I'm already set.Woof!Woof!Woof!"
;
   
// The singleton method
   
public static function singleton()
    {   
        if (!isset(
self::$instance)) {
           
$c = __CLASS__;
           
self::$instance = new $c;
           
#return self::$instance;
       
}
        echo
"Sorry but I'm already set.";
        return
self::$instance; ##...wrong place for this!comment this, uncomment it above
   
}   
?>
<?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();
$again = Example::singleton();
$and_again = Example::singleton();
$test->bark();
$again->bark();
$and_again->bark();
?>

marshall dot mattingly at NOSPAM dot gmail dot com (17-Apr-2009 05:56)

Here's my singleton class for php 5.3.0:

<?php
class Singleton {
 
// this must be in every inherited singleton!
 
protected static $_instance;

 
// get the instance
 
final public static function instance() {
   
// create the instance if we don't have one
   
if (empty(static::$_instance)) {
     
$class = get_called_class(); // php 5.3.0
     
static::$_instance = new $class;
    }

    return static::
$_instance;
  }

 
// must protect the constructor
 
protected function __construct() { }

 
// overload __clone
 
final public function __clone() {
    throw new
Exception('Cannot duplicate a singleton.');
  }
}

// a sample extension
class Extension extends Singleton {
 
// has to be here, sadly... if only statics were inherited
 
protected static $_instance;

  protected function
__construct() { ... }

  public function
foo() {
    echo
'foo\n';
  }
}

// example
$extension = Extension::instance();
$extension->foo(); // echo's 'foo\n' as expected
?>

Having to add "protected static $_instance" to every singleton is somewhat annoying. I tried the obvious alternative and stored all the instances within an array in the Singleton class. I ran Extension::getInstance() 1,000,000 over 10 runs to see which method was faster:

Array of $_instances:  3.47s average
Individual $_instance: 1.75s average

Considering the array of instances only had 1 key to search through, it's reasonable to assume that method would get slower as singletons are added, whereas the method above will always stay the same speed. The difference was enough for me to suffer the minor inconvenience.

grummfy at gmail dot com (06-Apr-2009 05:23)

Well, for non-php 5.3 users, another way is replacing get_called_class() by get_class(self) ou get_class($this).

grummfy at gmail dot com (06-Apr-2009 04:33)

Exemple of singleton that can be used for other class (need phpversion >= 5.3)
<?php
class SingletonModel
{
   
/**
     * Instance of singleton's class
     *
     * @var array
     */
   
private static $_instance;

   
/**
     * All constructeur should be protected
     */
   
protected function __construct(){}

   
/**
     * Singleton method to load a new object
     *
     * @return HlPwd_SingletonModel
     */
   
public static function singleton()
    {
        if (!isset(
self::$instance[ get_called_class() ]))
        {
           
$c = get_called_class();
           
self::$instance = new $c;
        }
       
        return
self::$instance;
    }

   
/**
     * Destroy the singleton
     */
   
public function destroySingleton()
    {
        unset(
self::$_instance[ get_class($this) ]);
    }

   
/**
     * Destructeur
     */
   
public function __destruct()
    {
        unset(
self::$_instance);
    }

   
/**
     * Impeach the clone of singleton
     */
   
public function __clone()
    {
       
trigger_error('Cloning not allowed on a singleton object', E_USER_ERROR);
    }
}

# EOF

you can easyli use it  like that

class mySingChild extends SingletonModel
{
    protected function
__construct()
    {
       
//do important things
   
}

    public function
foo()
    {
        echo
'hello world';
    }
}

$t = mySingChild::singleton();
$t->foo();

Talraith (12-Mar-2009 04:42)

I think a simpler option is to have a loader class/object and then the actual class.  It keeps your class more secure in that you are defining the visibility on $instances and you keep your class neat and tidy.

I found this useful when trying to use the singleton method on a class that extends another class.

<?php

class module_loader {
    private static
$instances;

    public static function
getInstance($module_name) {
        if (!isset(
self::$instances[$module_name])) {
           
self::$instances[$module_name] = new $module_name();
        }

        return
self::$instances[$module_name];
    }
}

class
module_base {
   
proteced $name;

    public function
__construct() {
       
// Do initialization stuff here

   
}

    public final function
SomePermanentFunction() {
       
// Perform function actions
   
}
}

class
module_test extends module_base {
    public
$my_var;

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

       
$this->name = 'test';
       
$this->my_var = '';
    }

    public function
ModuleSpecificFunction() {

    }
}

?>

So then once you have all of that defined, you can then use it like such:

<?php

// Get first instance and set value
$instance1 = module_loader::getInstance('module_test');
$instance1->my_var = 'abc';

print
"Instance 1 Var = " . $instance1->my_var;

// Create second instance and check value
$instance2 = module_loader::getInstance('module_test');

print
"Instance 2 Var = " . $instance2->my_var;

// Set value on second instance, check first instance
$instance2->my_var = 'def';

print
"Instance 1 Var = " . $instance1->my_var;

?>

The output would then look like this:

Instance 1 Var = abc
Instance 2 Var = abc
Instance 1 Var = def

Thus $instance1 and $instance2 are created using the factory pattern but they both point back to the same object (singleton pattern).

vaddsm(at)gmail.com (22-Jan-2009 08:34)

Hello! I want to suggest another fast and universal way to create a singleton, that can store instances any class types. The idea based on php's ability to create object's properties in run time, and magic functions support. Main trick is to create not existed property in __get method and assign to it a value of new instance of class, named as property.

Code:

<?php

class fClassOne
{

 public function
get()
 {
  return
"value 1<br>\n";
 }

 public function 
__construct()
 {
  echo
"fClassOne constructed<br>\n";
 }

}

class
fClassTwo
{

 public function
get()
 {
  return
"value 2<br>\n";
 }

 public function 
__construct()
 {
  echo
"fClassTwo constructed<br>\n";
 }

}

class
fSingleton
{
 public function
__get($sClassName)
 {
  echo
"isset check<br>\n";
  if(!isset(
$this->{$sClassName})) $this->{$sClassName} = new $sClassName;
  return
$this->{$sClassName};
 }
}

$MySingleton = new fSingleton();

for (
$i = 0; $i < 5; $i++) echo $MySingleton->fClassOne->get();

echo
$MySingleton->fClassTwo->get();
echo
$MySingleton->fClassTwo->get();

 
?>

Output:

isset check
fClassOne constructed
value 1
value 1
value 1
value 1
value 1
isset check
fClassTwo constructed
value 2
value 2

Anonymous (31-Dec-2008 07:34)

1: The singleton pattern ensures that only one instance of a class is ever created. Thus, applying it to a database connection object is common, since reusing a connection reduces latency and slows down reaching the database server's connection limit. If a database connection is only made in the singleton's constructor then it is probably impossible to accidentally open another connection via that object.

I say "probably impossible" because there are still some other issues: in this example, an invalid database connection identifier can be stored, retrieved, or lost (since it is an unserializable resource type) via object serialization without careful attention to the __sleep and __wakeup magic methods (and probably won't be valid on deserialization even if it is retained), and the __clone magic method should be implemented in a way that prevents object duplication.

(This example also ignores database connection pooling to stay focused on singletons.)

2: A singleton does not contain itself; it contains a reference to itself, which is conceptually similar to a pointer from the C language or a reference from Java. (In fact these are all very different under the hood and in practice, but I will ignore this for simplicity.)

Consider the following typical PHP 5.0 to 5.2 implementation:

<?php
class Example {
   
    private static
$instance;
   
    private
__construct() {
       
// Do important initializations here, like normal.
   
}
   
    public static function
getInstance() {
        if (
null == self::$instance):
           
// First invocation only.
           
$className = __CLASS__;
           
self::$instance = new $className();
        endif;
        return
self::$instance;
    }
   
    public function
__clone() {
        throw new
Exception('Illegally attempted to clone ' . __CLASS__);
    }
}
?>

Static class member variables can exist even without an instance of their class, and static class methods can be invoked without a class instance as well. The member variable that holds a reference to the singleton class instance ($instance) is static, as is the method to instantiate a singleton object (Example::getInstance()). Note that the variable $instance is private, so it cannot be affected by anything external to the class (thus preventing outside code from creating an instance of Example).

Static member variables are not really "inside" a class; each class instance points to the same static member variables as other instances, "sharing" these static variables between them (in a way) even before any class instances exist. Thus, Example::getInstance() always checks the same $instance variable.

3: The constructor has an access specifier of "private" to prevent direct instantiation using the "new" operator. (Prior to the implementation of the __callStatic features of PHP 5.3 it is not useful to mark the constructor "protected" since subclasses won't automatically also be singletons.) However, private methods can be invoked from a class's other methods; the static method Example::getInstance() is therefore allowed to invoke the private constructor. On first invocation, it creates an instance of Example and stores a reference to it in $instance. Subsequently, it just returns this reference.

4: The singleton pattern makes a class (slightly) more complicated, and the overhead of invoking its instantiation method is probably slightly higher than accessing a global variable instead. However, the benefits are substantial from an architectural perspective: it helps prevent performance losses due to accidentally instantiating more than one heavyweight class, it helps prevent bugs due to accidentally instantiating more than one instance of a class (such as a class that renders the requested HTML document in an online content management system), and helps keeps your global namespace and other lexical scopes clean even prior to the introduction of proper namespaces in PHP 5.3 (thus helping to prevent accidental variable clobbering or unexpected initial variable values from a previous module).

k at tamayuz dot com (13-Oct-2008 09:59)

Till now writing singleton classes depends on making class constructor private or protected and that sounds good, but what if class constructor must be public (for example, a singleton class inherits from a non-singleton class which already has a public constructor). The way to do so is:

<?php
   
class nonSingleton
   
{
        protected
$_foo;
       
        public function
__construct($foo)
        {
           
$this -> _foo = $foo;
        }
    }
   
    class
Singleton extends nonSingleton
   
{
       
/**
         * Single instance of the class
         *
         * @var Singleton
         */
       
protected static $_instance = NULL;
       
/**
         * A flag to know if we are in getInstance method or not.
         *
         * @var bool
         */
       
protected static $_withinGetInstance = false;
       
       
/**
         * Public singleton class constructor
         *
         * @param mixed $foo
         */
       
public function __construct($foo)
        {
            if (!
self :: $_withinGetInstance)
                throw new
Exception('You cannot make a new instance of this class by using constructor, use getInstance() instead...');
           
parent :: __construct($foo);
           
/*
                Any other operations constructor should do...
            */
       
}
       
       
/**
         * Regular getInstance method
         *
         * @param mixed $foo
         * @return Singleton
         */
       
public static function getInstance($foo)
        {
           
self :: $_withinGetInstance = true;
            if (!
self :: $_instance)
               
self :: $_instance = new Singleton($foo);
           
self :: $_withinGetInstance = false;
            return
self :: $_instance;
        }
    }
?>

Anonymous (30-Sep-2008 01:44)

Let me describe another pattern it is called “Decorator”. It can be used to add features to already written object. It is useful for extending some library classes from your framework without changing the original classes (especially if somebody else wrote those). The actual meaning is best presented in an example.

<?php
// the main interface in which we going to do some decoration
interface salad{
    public function
wait();
}

// main class which is already defined and you can't or don't want to change
class shopSalad implements salad{
    private
$tomatoes;
    private
$cucumbers;
    private
$cheese;
   
    public function
__construct($tomatoes, $cucumbers, $cheese){
       
$this->tomatoes = $tomatoes;
       
$this->cucumbers = $cucumbers;
       
$this->cheese = $cheese;
    }
   
    public function
wait(){
        echo
"the salad is served using {$this->tomatoes} tomatoes, {$this->cucumbers} cucumbers and {$this->cheese} gr. of cheese.";
    }
}

// abstract decorator class - note that it implements salad
abstract class saladDecorator implements salad{
    protected
$salad// the object for decoration
   
public function __construct(salad $salad){
       
$this->salad=$salad;
    }
   
// there is no need to mention the wait function therefore this class inherits the original salad
    // the purpose of this class is maintaining the type of the object produced by the decorators.
    // it inherits the same interface as the original and it will be inherited by the concrete decorators
}

// sauce decorator
class saladSauce extends saladDecorator {
    public function
wait(){
       
$this->salad->wait();
        echo
" Then it was decorated with some sauce.";
       
    }
}

// onions decorator
class saladOnions extends saladDecorator {
    public function
wait(){
       
$this->salad->wait();
        echo
" Then it was decorated with some onions.";
    }
}

$order1 = new shopSalad(2,1,100); // creates the salad in the normal way
$order1 = new saladSauce($order1); // add a decorator to the class
$order1->wait();
echo
'<br />';

// or
$order3 = new saladOnions(new saladSauce(new shopSalad(1,0.5,50))); // you don't need to load a variable with the reference
$order3->wait();
?>

this will outputs:
the salad is served using 2 tomatoes, 1 cucumbers and 100 gr. of cheese. Then it was decorated with some sauce.
the salad is served using 3 tomatoes, 2 cucumbers and 100 gr. of cheese. Then it was decorated with some onions. Then it was decorated with some sauce.
the salad is served using 1 tomatoes, 0.5 cucumbers and 50 gr. of cheese. Then it was decorated with some souse. Then it was decorated with some onions.

The pattern is not intended to be used with simple object and I couldn't do more simple than that. The pattern is useful in every way when the extending of an object is required. It can be used to divide some methods from others or to create layers of interaction with the object. In example if you have an file interface and a imageFile class which implements the file and then you can have also an textFile for the textFile you can do some layering and if you want to read the file as XML you can mace a decorator to do so. The XML decorator will inherit the interface file so you can save it and    the instance of textFile will be given to create the decorator so you can read the actual text and pars it as XML. It is possible the file to be .ini or some other text based document and you can make a decorator for every one of them. This is the actual benefit of the pattern.

Partty (30-Sep-2008 12:13)

The singleton effect you are applying to can be achieved in a old-fashioned and simpler way. Remember that the 'static' is the way for sharing the data between the objects from one type. And there is no pattern in this. So the only think you can do is to use the static keyword. If your program is already written and the rewrite is not recommended there is the "adapter pattern" witch can be used. It is intended to adapt an object to an already build environment. This is one way to have singleton functionality without actually the singleton pattern, it uses a class with static data and static methods and a adaptor class to adapt those methods to your interface.

The example shows how the every instance of the singlePoint class givs you the same data.
<?php
class single {
   
    static
$a;
    static
$b;
   
    protected static function
_start($a,$b){
       
self::$a=$a;
       
self::$b=$b;
    }
    protected static function
_get_a(){
        return
self::$a;
    }
    protected static function
_get_b(){
        return
self::$b;
    }
}
class
singlePoint extends single {
    public function
__construct($a='',$b=''){
        if(
$a!='' && $b!=''){
           
single::_start($a,$b);
        }
    }
    public function
get_a(){
        return
single::_get_a();
    }
    public function
get_b(){
        return
single::_get_b();
    }
}

class
scopeTest{
    public function
__construct(){
       
$singlePointInstance = new singlePoint();
        echo
'In scopeTest a='.$singlePointInstance->get_a().'<br />';
    }
}

$theSingle = new singlePoint(3,5);
echo
'In index a='.$theSingle->get_a().'<br />';

$theScopeTest = new scopeTest();
?>

My point is that you don't need single instance of the class but you need access to the same data over and over again ant the build in way to do that in every language I know so far is the 'static' keyword. It was engineered to give you this functionality. All the singleton patterns and even this adapter is unnecessary complication of the structure. KISS = “Keep It Simple Stupid” no need of that!

Mattlock (07-Sep-2008 02:49)

I've been forward-developing for PHP 5.3, and couldn't help but notice that late-static-binding makes implementing Singletons simple. Its even easy to set up some function forwarding so that static calls are transformed into non-staic calls:

<?php
// Requires PHP 5.3!
class Singleton {
    public static function
Instance() {
        static
$instances = array();
       
$class = get_called_class();
        if (!
array_key_exists($class, $instances)) {
           
$instances[$class] = new $class();
        }
        return
$instances[$class];
    }
    public static function
__callStatic($func, $args) {
       
$class = static::Instance();
        return
call_user_func_array(array($class, '__'.$func), $args);
    }
}

class
Earth extends Singleton {
    public function
__DoSomething($a, $b) {
        return
15 + $this->SomethingElse($a, $b);
    }
    protected function
SomethingElse($c, $d) {
        return
$c % $d;
    }
}

echo
Earth::DoSomething(6,27);
?>

alexander gavazov (27-Aug-2008 03:05)

For quick instance access use function
<?php
class Example{....}

function
Example {
  return
Example::getInstance();
}

// Global access
Example()->sayHallo(...);
Example()->doSomething(...);
print
Example()->someData;
?>

Alex (raffe) toader_alexandru at yahoo dot com (03-Jun-2008 07:04)

Db layer design algorithm:
"Separation of database layer by database functionality"

First we draw this line:

Application
-------------
     DB

Here comes the new thing:
The db layer we separate it into two areas like this:

Db layer
       |
select | insert, update delete
       |

in the left side we have the select part.
The difference between the left and the right sides is that select side has no connection with the db structure - you can take data querying all table, while the right side is table oriented.

Select side:
Here all queries are in one file called "getters". Like getterUsers.

Inside it will be the body of the query but the fields that are to be selected will be build dynamically.
When calling this "getter" you will provide an array of fields to be selected or no fields, situation when it will take all fields.

To keep those db field names as low as possible in this architecture - so the above code dont need to know about the name of the fields in db, you will make just above this "getter", a "filter" file.
This filter will have a switch with a key and inside will call the getter with fields from db.
Ex:
<?php
switch(key)
case
'Label':
$fields = array("label", "firstName");
$obj->getUser($fields)
break;
?>

Above this filter you will have a "caller" that will call the "filter" with the key:
Ex:
<?php
function callerUserLabel()
{
->
filterUserLabel('Label');
}
?>

So in the higher code you just make
->callerUserLabel();
and this will return all what you need.

If you want this query to get out of the db and another field called "email", you just create another case in the switch and a "caller" to call that case.

Dynamic and extensible.

----------------

Now on the insert update side.
Here we only think in db tables.

First we do some "checkers" for all fields in db.
checkerTableName.php
This will contain an array with all the fields and the checks that must be done on that field and perform the checks only on the provided fields.

Then we do the "updaters". Those are build dinamically like the "getters" - if fields provided, only those updated. If all fields provided, can be used as an "inserter".

When performing an insert, all checks on that table will be done.

When performing an update on only one field - like updating a label, only that label will be checked to be in conformity with requirements like a length, special chars inside.
Dependency checks are made here also.

When having in one application action a multiple insert or update (when inserting an operator also add a webUser lets say) you do above those "inserter" and "updater" files a small "manager" that will do:
->checkOperatorFields();
->checkWebUserFields();

->insertOperator();
->insertWebUser();

If no error is thrown, all things will go nice and quiet.

Now also the "getters" will have their fields checked when needed using those checkers. I am talking about the values that are given as parameters not about the ones that are returned from db.

If you are working with domain objects or business logic objects (whatever you call them) above the db layer you will have to make below that line we first draw a "business logic asambler" object that will make from your data what you want.

If this dont exist, at least an intermediary layer that will map the names from db with the ones used in application must be done in both directions - from application to db and from db to application.

-------------------------------------

Advantages of this architecture:
- Usefull in complex application especheally where the selects are made ussually from many tables so you dont have to load lots and lots of files and to get lost in the logic for one simple select.
- NO DUPLICATE CODE
- Simple and intuitive.
- Flexible and expendable.

Andrea Giammarchi (01-Jun-2008 06:49)

A tricky way to implement Factory or Singleton is this one:
<?php

class A {
   
// your amazing stuff
}

// implicit factory
function A( /* one or more args */ ){
    return new
A( /* one or more args */ );
}

$a = A(1,2,3);
$b = A(2,3);

// or implicit Singleton
function A( /* one or more args */ ){
    static
$instance;
    return isset(
$instance) ? $instance : ($instance = new A( /* one or more args */ ));
}

A(1,2,3) === A(2,3); // true
?>

More details in WebReflection, byez

someone at somewhere dot com (05-May-2008 09: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

Mattlock (21-Feb-2008 04: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>';
?>

Alexandre at dontspamme gaigalas dot net (09-Jan-2008 09: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();
    }
}
?>

dario [dot] ocles [at] gmail [dot] com (18-Jun-2007 11: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.

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.

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 01:38)

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 08:19)

An easy way to have your singleton persistent between page loads:

<?php
/**
 *    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__;
?>

cortex at pressemicro dot net (02-Jun-2006 09: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 11: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.

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...

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);

?>

steffen at morkland dot com (11-Oct-2005 03: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 05:25)

Short version of Singleton:
<?php
public function __clone()
    {
       
trigger_error('Clone is not allowed.', E_USER_ERROR);
    }
?>
   
is :
<?php private function __clone() {} ?>

lukas dot starecek at centrum dot cz (17-Jul-2005 09:12)

If you need singleton of any class and don't want write singleton wrapper for each this class, try this:

<?php
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 07: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 05: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 07: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.

anon at anon dot org (23-May-2005 09: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 10: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);
}

// Create a MeowCat with scary eyes and whiskers
$cat = createCat('Meow', TRUE);
// Do whatever
?>