Creating the Singleton design pattern in PHP5
/** * 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 static variable scopes and why setting static $inst = null;
works.
Unfortunately Inwdr's answer breaks when there are multiple subclasses.
Here is a correct inheritable 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 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 solves the problem, that prior to PHP 5.3 any class that extended a Singleton would produce an instance of its parent class instead of its own.
Now you can do:
class Foobar extends Singleton {};$foo = Foobar::getInstance();
And $foo will be an instance of Foobar instead of an instance of Singleton.