Creating the Singleton design pattern in PHP5

2018-12-31 06:39发布

How would one create a Singleton class using PHP5 classes?

20条回答
回忆,回不去的记忆
2楼-- · 2018-12-31 07:04
class Database{

        //variable to hold db connection
        private $db;
        //note we used static variable,beacuse an instance cannot be used to refer this
        public static $instance;

        //note constructor is private so that classcannot be instantiated
        private function __construct(){
          //code connect to database  

         }     

         //to prevent loop hole in PHP so that the class cannot be cloned
        private function __clone() {}

        //used static function so that, this can be called from other classes
        public static function getInstance(){

            if( !(self::$instance instanceof self) ){
                self::$instance = new self();           
            }
             return self::$instance;
        }


        public function query($sql){
            //code to run the query
        }

    }


Access the method getInstance using
$db = Singleton::getInstance();
$db->query();
查看更多
浅入江南
3楼-- · 2018-12-31 07:05
protected  static $_instance;

public static function getInstance()
{
    if(is_null(self::$_instance))
    {
        self::$_instance = new self();
    }
    return self::$_instance;
}

This code can apply for any class without caring about its class name.

查看更多
长期被迫恋爱
4楼-- · 2018-12-31 07:09

This article covers topic quite extensively: http://www.phptherightway.com/pages/Design-Patterns.html#singleton

Note the following:

  • The constructor __construct() is declared as protected to prevent creating a new instance outside of the class via the new operator.
  • The magic method __clone() is declared as private to prevent cloning of an instance of the class via the clone operator.
  • The magic method __wakeup() is declared as private to prevent unserializing of an instance of the class via the global function unserialize().
  • A new instance is created via late static binding in the static creation method getInstance() with the keyword static. This allows the subclassing of the class Singleton in the example.
查看更多
泛滥B
5楼-- · 2018-12-31 07:13

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

private function __clone() {}

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

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

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

查看更多
弹指情弦暗扣
6楼-- · 2018-12-31 07:13

All this complexity ("late static binding" ... harumph) is, to me, simply a sign of PHP's broken object/class model. If class objects were first-class objects (see Python), then "$_instance" would be a class instance variable -- a member of the class object, as opposed to a member/property of its instances, and also as opposed to shared by its descendants. In the Smalltalk world, this is the difference between a "class variable" and a "class instance variable".

In PHP, it looks to me as though we need to take to heart the guidance that patterns are a guide towards writing code -- we might perhaps think about a Singleton template, but trying to write code that inherits from an actual "Singleton" class looks misguided for PHP (though I supposed some enterprising soul could create a suitable SVN keyword).

I will continue to just code each singleton separately, using a shared template.

Notice that I'm absolutely staying OUT of the singletons-are-evil discussion, life is too short.

查看更多
浪荡孟婆
7楼-- · 2018-12-31 07:13

I liked @jose-segura method of using traits but didn't like the need to define a static variable on sub-classes. Below is a solution that avoids it by caching the instances in a static local variable to the factory method indexed by class name:

<?php
trait Singleton {

  # Single point of entry for creating a new instance. For a given
  # class always returns the same instance.
  public static function instance(){
    static $instances = array();
    $class = get_called_class();
    if( !isset($instances[$class]) ) $instances[$class] = new $class();
    return $instances[$class];
  }

  # Kill traditional methods of creating new instances
  protected function __clone() {}
  protected function __construct() {}
}

Usage is the same as @jose-segura only no need for the static variable in sub-classes.

查看更多
登录 后发表回答