[ACCEPTED]-Creating the Singleton design pattern in PHP5-singleton
/**
* Singleton class
*
*/
final class UserFactory
{
/**
* Call this method to get singleton
*
* @return UserFactory
*/
public static function Instance()
{
static $inst = null;
if ($inst === null) {
$inst = new UserFactory();
}
return $inst;
}
/**
* Private ctor so nobody else can instantiate it
*
*/
private function __construct()
{
}
}
To use:
$fact = UserFactory::Instance();
$fact2 = UserFactory::Instance();
$fact == $fact2;
But:
$fact = new UserFactory()
Throws an error.
See http://php.net/manual/en/language.variables.scope.php#language.variables.scope.static to understand 1 static variable scopes and why setting static $inst = null;
works.
Unfortunately Inwdr's answer breaks when there are multiple 2 subclasses.
Here is a correct inheritable 1 Singleton base class.
class Singleton
{
private static $instances = array();
protected function __construct() {}
protected function __clone() {}
public function __wakeup()
{
throw new Exception("Cannot unserialize singleton");
}
public static function getInstance()
{
$cls = get_called_class(); // late-static-bound class name
if (!isset(self::$instances[$cls])) {
self::$instances[$cls] = new static;
}
return self::$instances[$cls];
}
}
Test code:
class Foo extends Singleton {}
class Bar extends Singleton {}
echo get_class(Foo::getInstance()) . "\n";
echo get_class(Bar::getInstance()) . "\n";
PHP 5.3 allows the creation of an inheritable 7 Singleton class via late static binding:
class Singleton
{
protected static $instance = null;
protected function __construct()
{
//Thou shalt not construct that which is unconstructable!
}
protected function __clone()
{
//Me not like clones! Me smash clones!
}
public static function getInstance()
{
if (!isset(static::$instance)) {
static::$instance = new static;
}
return static::$instance;
}
}
This 6 solves the problem, that prior to PHP 5.3 5 any class that extended a Singleton would 4 produce an instance of its parent class 3 instead of its own.
Now you can do:
class Foobar extends Singleton {};
$foo = Foobar::getInstance();
And $foo 2 will be an instance of Foobar instead of 1 an instance of Singleton.
The Real One and Modern way to make Singleton Pattern is:
<?php
/**
* Singleton Pattern.
*
* Modern implementation.
*/
class Singleton
{
/**
* Call this method to get singleton
*/
public static function instance()
{
static $instance = false;
if( $instance === false )
{
// Late static binding (PHP 5.3+)
$instance = new static();
}
return $instance;
}
/**
* Make constructor private, so nobody can call "new Class".
*/
private function __construct() {}
/**
* Make clone magic method private, so nobody can clone instance.
*/
private function __clone() {}
/**
* Make sleep magic method private, so nobody can serialize instance.
*/
private function __sleep() {}
/**
* Make wakeup magic method private, so nobody can unserialize instance.
*/
private function __wakeup() {}
}
So now 2 you can use it like.
<?php
/**
* Database.
*
* Inherited from Singleton, so it's now got singleton behavior.
*/
class Database extends Singleton {
protected $label;
/**
* Example of that singleton is working correctly.
*/
public function setLabel($label)
{
$this->label = $label;
}
public function getLabel()
{
return $this->label;
}
}
// create first instance
$database = Database::instance();
$database->setLabel('Abraham');
echo $database->getLabel() . PHP_EOL;
// now try to create other instance as well
$other_db = Database::instance();
echo $other_db->getLabel() . PHP_EOL; // Abraham
$other_db->setLabel('Priler');
echo $database->getLabel() . PHP_EOL; // Priler
echo $other_db->getLabel() . PHP_EOL; // Priler
As you see this realization 1 is lot more flexible.
You probably should add a private __clone() method 4 to disallow cloning of an instance.
private function __clone() {}
If you 3 don't include this method the following 2 gets possible
$inst1=UserFactory::Instance(); // to stick with the example provided above
$inst2=clone $inst1;
now $inst1
!== $inst2
- they are not the 1 same instance any more.
<?php
/**
* Singleton patter in php
**/
trait SingletonTrait {
protected static $inst = null;
/**
* call this method to get instance
**/
public static function getInstance(){
if (static::$inst === null){
static::$inst = new static();
}
return static::$inst;
}
/**
* protected to prevent clonning
**/
protected function __clone(){
}
/**
* protected so no one else can instance it
**/
protected function __construct(){
}
}
to use:
/**
* example of class definitions using SingletonTrait
*/
class DBFactory {
/**
* we are adding the trait here
**/
use SingletonTrait;
/**
* This class will have a single db connection as an example
**/
protected $db;
/**
* as an example we will create a PDO connection
**/
protected function __construct(){
$this->db =
new PDO('mysql:dbname=foodb;port=3305;host=127.0.0.1','foouser','foopass');
}
}
class DBFactoryChild extends DBFactory {
/**
* we repeating the inst so that it will differentiate it
* from UserFactory singleton
**/
protected static $inst = null;
}
/**
* example of instanciating the classes
*/
$uf0 = DBFactoryChild::getInstance();
var_dump($uf0);
$uf1 = DBFactory::getInstance();
var_dump($uf1);
echo $uf0 === $uf1;
respose:
object(DBFactoryChild)#1 (0) {
}
object(DBFactory)#2 (0) {
}
If you are using PHP 5.4: trait its 7 an option, so you don't have to waste the 6 inheritance hierarchy in order to have the 5 Singleton pattern
and also notice that whether you use traits or 4 extends Singleton class one loose end was to create singleton 3 of child classes if you dont add the following 2 line of code:
protected static $inst = null;
in the child class
the unexpected 1 result will be:
object(DBFactoryChild)#1 (0) {
}
object(DBFactoryChild)#1 (0) {
}
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 1 caring about its class name.
Supports Multiple Objects with 1 line per class:
This method will enforce singletons on any 16 class you wish, al you have to do is add 15 1 method to the class you wish to make a 14 singleton and this will do it for you.
This 13 also stores objects in a "SingleTonBase" class 12 so you can debug all your objects that you 11 have used in your system by recursing the 10 SingleTonBase
objects.
Create a file called SingletonBase.php 9 and include it in root of your script!
The 8 code is
abstract class SingletonBase
{
private static $storage = array();
public static function Singleton($class)
{
if(in_array($class,self::$storage))
{
return self::$storage[$class];
}
return self::$storage[$class] = new $class();
}
public static function storage()
{
return self::$storage;
}
}
Then for any class you want to make 7 a singleton just add this small single method.
public static function Singleton()
{
return SingletonBase::Singleton(get_class());
}
Here 6 is a small example:
include 'libraries/SingletonBase.resource.php';
class Database
{
//Add that singleton function.
public static function Singleton()
{
return SingletonBase::Singleton(get_class());
}
public function run()
{
echo 'running...';
}
}
$Database = Database::Singleton();
$Database->run();
And you can just add 5 this singleton function in any class you 4 have and it will only create 1 instance 3 per class.
NOTE: You should always make the 2 __construct private to eliminate the use 1 of new Class(); instantiations.
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();
0
You don't really need to use Singleton pattern 10 because it's considered to be an antipattern. Basically 9 there is a lot of reasons to not to implement 8 this pattern at all. Read this to start 7 with: Best practice on PHP singleton classes.
If after all you still think you 6 need to use Singleton pattern then we could 5 write a class that will allow us to get 4 Singleton functionality by extending our 3 SingletonClassVendor abstract class.
This 2 is what I came with to solve this problem.
<?php
namespace wl;
/**
* @author DevWL
* @dosc allows only one instance for each extending class.
* it acts a litle bit as registry from the SingletonClassVendor abstract class point of view
* but it provides a valid singleton behaviour for its children classes
* Be aware, the singleton pattern is consider to be an anti-pattern
* mostly because it can be hard to debug and it comes with some limitations.
* In most cases you do not need to use singleton pattern
* so take a longer moment to think about it before you use it.
*/
abstract class SingletonClassVendor
{
/**
* holds an single instance of the child class
*
* @var array of objects
*/
protected static $instance = [];
/**
* @desc provides a single slot to hold an instance interchanble between all child classes.
* @return object
*/
public static final function getInstance(){
$class = get_called_class(); // or get_class(new static());
if(!isset(self::$instance[$class]) || !self::$instance[$class] instanceof $class){
self::$instance[$class] = new static(); // create and instance of child class which extends Singleton super class
echo "new ". $class . PHP_EOL; // remove this line after testing
return self::$instance[$class]; // remove this line after testing
}
echo "old ". $class . PHP_EOL; // remove this line after testing
return static::$instance[$class];
}
/**
* Make constructor abstract to force protected implementation of the __constructor() method, so that nobody can call directly "new Class()".
*/
abstract protected function __construct();
/**
* Make clone magic method private, so nobody can clone instance.
*/
private function __clone() {}
/**
* Make sleep magic method private, so nobody can serialize instance.
*/
private function __sleep() {}
/**
* Make wakeup magic method private, so nobody can unserialize instance.
*/
private function __wakeup() {}
}
Use 1 example:
/**
* EXAMPLE
*/
/**
* @example 1 - Database class by extending SingletonClassVendor abstract class becomes fully functional singleton
* __constructor must be set to protected becaouse:
* 1 to allow instansiation from parent class
* 2 to prevent direct instanciation of object with "new" keword.
* 3 to meet requierments of SingletonClassVendor abstract class
*/
class Database extends SingletonClassVendor
{
public $type = "SomeClass";
protected function __construct(){
echo "DDDDDDDDD". PHP_EOL; // remove this line after testing
}
}
/**
* @example 2 - Config ...
*/
class Config extends SingletonClassVendor
{
public $name = "Config";
protected function __construct(){
echo "CCCCCCCCCC" . PHP_EOL; // remove this line after testing
}
}
Just to prove that it works as expected:
/**
* TESTING
*/
$bd1 = Database::getInstance(); // new
$bd2 = Database::getInstance(); // old
$bd3 = Config::getInstance(); // new
$bd4 = Config::getInstance(); // old
$bd5 = Config::getInstance(); // old
$bd6 = Database::getInstance(); // old
$bd7 = Database::getInstance(); // old
$bd8 = Config::getInstance(); // old
echo PHP_EOL."COMPARE ALL DATABASE INSTANCES".PHP_EOL;
var_dump($bd1);
echo '$bd1 === $bd2' . ($bd1 === $bd2)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd2 === $bd6' . ($bd2 === $bd6)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd6 === $bd7' . ($bd6 === $bd7)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo PHP_EOL;
echo PHP_EOL."COMPARE ALL CONFIG INSTANCES". PHP_EOL;
var_dump($bd3);
echo '$bd3 === $bd4' . ($bd3 === $bd4)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd4 === $bd5' . ($bd4 === $bd5)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
echo '$bd5 === $bd8' . ($bd5 === $bd8)? ' TRUE' . PHP_EOL: ' FALSE' . PHP_EOL; // TRUE
I know this is probably going to cause an 47 unnecessary flame war, but I can see how 46 you might want more than one database connection, so 45 I would concede the point that singleton 44 might not be the best solution for that... however, there 43 are other uses of the singleton pattern 42 that I find extremely useful.
Here's an example: I 41 decided to roll my own MVC and templating 40 engine because I wanted something really 39 lightweight. However, the data that I want 38 to display contains a lot of special math 37 characters such as ≥ and μ and what 36 have you... The data is stored as the actual 35 UTF-8 character in my database rather than 34 pre-HTML-encoded because my app can deliver 33 other formats such as PDF and CSV in addition 32 to HTML. The appropriate place to format 31 for HTML is inside the template ("view" if 30 you will) that is responsible for rendering 29 that page section (snippet). I want to convert 28 them to their appropriate HTML entities, but 27 PHPs get_html_translation_table() function 26 is not super fast. It makes better sense 25 to retrieve the data one time and store 24 as an array, making it available for all 23 to use. Here's a sample I knocked together 22 to test the speed. Presumably, this would 21 work regardless of whether the other methods 20 you use (after getting the instance) were 19 static or not.
class EncodeHTMLEntities {
private static $instance = null;//stores the instance of self
private $r = null;//array of chars elligalbe for replacement
private function __clone(){
}//disable cloning, no reason to clone
private function __construct()
{
$allEntities = get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES);
$specialEntities = get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES);
$this->r = array_diff($allEntities, $specialEntities);
}
public static function replace($string)
{
if(!(self::$instance instanceof self) ){
self::$instance = new self();
}
return strtr($string, self::$instance->r);
}
}
//test one million encodings of a string
$start = microtime(true);
for($x=0; $x<1000000; $x++){
$dump = EncodeHTMLEntities::replace("Reference method for diagnosis of CDAD, but clinical usefulness limited due to extended turnaround time (≥96 hrs)");
}
$end = microtime(true);
echo "Run time: ".($end-$start)." seconds using singleton\n";
//now repeat the same without using singleton
$start = microtime(true);
for($x=0; $x<1000000; $x++){
$allEntities = get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES);
$specialEntities = get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES);
$r = array_diff($allEntities, $specialEntities);
$dump = strtr("Reference method for diagnosis of CDAD, but clinical usefulness limited due to extended turnaround time (≥96 hrs)", $r);
}
$end = microtime(true);
echo "Run time: ".($end-$start)." seconds without using singleton";
Basically, I saw typical results 18 like this:
php test.php Run time: 27.842966794968 seconds using singleton Run time: 237.78191494942 seconds without using singleton
So while I'm certainly no expert, I 17 don't see a more convenient and reliable 16 way to reduce the overhead of slow calls 15 for some kind of data, while making it super 14 simple (single line of code to do what you 13 need). Granted my example only has one 12 useful method, and therefore is no better 11 than a globally defined function, but as 10 soon as you have two methods, you're going 9 to want to group them together, right? Am 8 I way off base?
Also, I prefer examples that 7 actually DO something, since sometimes it's 6 hard to visualise when an example includes 5 statements like "//do something useful here" which 4 I see all the time when searching for tutorials.
Anyway, I'd 3 love any feedback or comments on why using 2 a singleton for this type of thing is detrimental 1 (or overly complicated).
All this complexity ("late static binding" ... harumph) is, to 21 me, simply a sign of PHP's broken object/class 20 model. If class objects were first-class 19 objects (see Python), then "$_instance" would 18 be a class instance variable -- a member of the 17 class object, as opposed to a member/property 16 of its instances, and also as opposed to 15 shared by its descendants. In the Smalltalk 14 world, this is the difference between a 13 "class variable" and a "class instance variable".
In 12 PHP, it looks to me as though we need to 11 take to heart the guidance that patterns 10 are a guide towards writing code -- we might 9 perhaps think about a Singleton template, but 8 trying to write code that inherits from 7 an actual "Singleton" class looks misguided 6 for PHP (though I supposed some enterprising 5 soul could create a suitable SVN keyword).
I 4 will continue to just code each singleton 3 separately, using a shared template.
Notice 2 that I'm absolutely staying OUT of the singletons-are-evil 1 discussion, life is too short.
This article covers topic quite extensively: http://www.phptherightway.com/pages/Design-Patterns.html#singleton
Note 1 the following:
- The constructor
__construct()
is declared asprotected
to prevent creating a new instance outside of the class via thenew
operator.- The magic method
__clone()
is declared asprivate
to prevent cloning of an instance of the class via theclone
operator.- The magic method
__wakeup()
is declared asprivate
to prevent unserializing of an instance of the class via the global functionunserialize()
.- A new instance is created via late static binding in the static creation method
getInstance()
with the keywordstatic
. This allows the subclassing of theclass Singleton
in the example.
I have written long back thought to share 1 here
class SingletonDesignPattern {
//just for demo there will be only one instance
private static $instanceCount =0;
//create the private instance variable
private static $myInstance=null;
//make constructor private so no one create object using new Keyword
private function __construct(){}
//no one clone the object
private function __clone(){}
//avoid serialazation
public function __wakeup(){}
//ony one way to create object
public static function getInstance(){
if(self::$myInstance==null){
self::$myInstance=new SingletonDesignPattern();
self::$instanceCount++;
}
return self::$myInstance;
}
public static function getInstanceCount(){
return self::$instanceCount;
}
}
//now lets play with singleton design pattern
$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();
echo "number of instances: ".SingletonDesignPattern::getInstanceCount();
I agree with the first answer but I would 10 also declare the class as final so that 9 it cannot be extended as extending a singleton 8 violates the singleton pattern. Also the 7 instance variable should be private so that 6 it cannot be accessed directly. Also make 5 the __clone method private so that you cannot 4 clone the singleton object.
Below is some 3 example code.
/**
* Singleton class
*
*/
final class UserFactory
{
private static $_instance = null;
/**
* Private constructor
*
*/
private function __construct() {}
/**
* Private clone method
*
*/
private function __clone() {}
/**
* Call this method to get singleton
*
* @return UserFactory
*/
public static function getInstance()
{
if (self::$_instance === null) {
self::$_instance = new UserFactory();
}
return self::$_instance;
}
}
Example Usage
$user_factory = UserFactory::getInstance();
What this stops 2 you from doing (which would violate the 1 singleton pattern..
YOU CANNOT DO THIS!
$user_factory = UserFactory::$_instance;
class SecondUserFactory extends UserFactory { }
This should be the right way of Singleton.
class Singleton {
private static $instance;
private $count = 0;
protected function __construct(){
}
public static function singleton(){
if (!isset(self::$instance)) {
self::$instance = new Singleton;
}
return self::$instance;
}
public function increment()
{
return $this->count++;
}
protected function __clone(){
}
protected function __wakeup(){
}
}
0
I liked @jose-segura method of using traits 7 but didn't like the need to define a static 6 variable on sub-classes. Below is a solution 5 that avoids it by caching the instances 4 in a static local variable to the factory 3 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 2 same as @jose-segura only no need for the 1 static variable in sub-classes.
Database class that checks if there is any 2 existing database instance it will return 1 previous instance.
class Database {
public static $instance;
public static function getInstance(){
if(!isset(Database::$instance) ) {
Database::$instance = new Database();
}
return Database::$instance;
}
private function __cunstruct() {
/* private and cant create multiple objects */
}
public function getQuery(){
return "Test Query Data";
}
}
$dbObj = Database::getInstance();
$dbObj2 = Database::getInstance();
var_dump($dbObj);
var_dump($dbObj2);
/*
After execution you will get following output:
object(Database)[1]
object(Database)[1]
*/
Ref http://www.phptechi.com/php-singleton-design-patterns-example.html
This is the example of create singleton on Database class
design patterns 1) singleton
class Database{
public static $instance;
public static function getInstance(){
if(!isset(Database::$instance)){
Database::$instance=new Database();
return Database::$instance;
}
}
$db=Database::getInstance();
$db2=Database::getInstance();
$db3=Database::getInstance();
var_dump($db);
var_dump($db2);
var_dump($db3);
then out put 2 is --
object(Database)[1]
object(Database)[1]
object(Database)[1]
use only single instance not create 1 3 instance
Quick example:
final class Singleton
{
private static $instance = null;
private function __construct(){}
private function __clone(){}
private function __wakeup(){}
public static function get_instance()
{
if ( static::$instance === null ) {
static::$instance = new static();
}
return static::$instance;
}
}
Hope help.
0
The above answers are ok, But I'll add more.
Whoever 5 come here in 2021, I'll show another example 4 of using Singleton
Pattern class as a trait
and Re-use 3 this in any class.
<?php
namespace Akash;
trait Singleton
{
/**
* Singleton Instance
*
* @var Singleton
*/
private static $instance;
/**
* Private Constructor
*
* We can't use the constructor to create an instance of the class
*
* @return void
*/
private function __construct()
{
// Don't do anything, we don't want to be initialized
}
/**
* Get the singleton instance
*
* @return Singleton
*/
public static function getInstance()
{
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Private clone method to prevent cloning of the instance of the
* Singleton instance.
*
* @return void
*/
private function __clone()
{
// Don't do anything, we don't want to be cloned
}
/**
* Private unserialize method to prevent unserializing of the Singleton
* instance.
*
* @return void
*/
private function __wakeup()
{
// Don't do anything, we don't want to be unserialized
}
}
So, use it like in any 2 class easily. Suppose, we want to implement 1 Singleton pattern in UserSeeder
class.
<?php
class UserSeeder
{
use Singleton;
/**
* Seed Users
*
* @return void
*/
public function seed()
{
echo 'Seeding...';
}
}
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.