Creating the Singleton design pattern in PHP5
/**
* Singleton class
*
*/
final class UserFactory
{
private static $inst = null;
// Prevent cloning and de-serializing
private function __clone(){}
private function __wakeup(){}
/**
* Call this method to get singleton
*
* @return UserFactory
*/
public static function Instance()
{
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.
Singleton in Conjunction with the Factory Pattern in PHP5
singleton factory for DB connection:
class Registry
{
private static $_objects;
public static function set($key, $object)
{
if (!array_key_exists($key, self::$_objects)) self::$_objects[$key] = $object;
}
public static function get($key)
{
if (array_key_exists($key, self::$_objects)) return self::$_objects[$key];
else return false;
}
}
class DBFactory
{
public static function getConnection($type)
{
switch ($type) {
case 'pdo':
if (!(Registry::get('DB_PDO') instaceof DbPdo)) Registry::set('DB_PDO', new DbPdo('user', 'pass', ...));
return Registry::get('DB_PDO')
case 'mssql':
//same for other connections
//...
}
}
}
usage:
$factory = DBFactory::getConnection('pdo');
Singletons are not really needed anymore because all methods can be called statically...
But the database classes can still be considered singletons because there will only be one single instance of them in your application.
So the same effect is created by using the factory and registry patterns.
The registry could be replaced by making your database classes singletons then the factory would look like this:
class DBFactory
{
public static function getConnection($type)
{
switch ($type) {
case 'pdo':
return DbPdo::getInstance('user', 'pass', ...);
case 'mssql':
//same for other connections
//...
}
}
}
class DbPdo
{
private static $_instance;
private function __construct($user, $pass, ...){ //instantiate object }
public static function getInstance($user = null, $pass = null, ...)
{
if (!(self::$_instance instanceof DbPdo)) self::$_instance = new DbPdo($user, $pass, ...);
return self::$_instance;
}
}
So you have the choice of making all your DB objects singletons or using a registry. I personally would go with a registry because it can be used to store any types of object, even the ones where you don't want to make the class a singleton.
Design choices are always subjected to personal flavor imo...
Creating a Singleton base class in PHP 5.3
Try using isset
rather than instanceof
:
class Singleton {
protected static $instances;
protected function __construct() { }
final private function __clone() { }
public static function getInstance() {
$class = get_called_class();
if (!isset(self::$instances[$class])) {
self::$instances[$class] = new $class;
}
return self::$instances[$class];
}
}
Singleton pattern not working in PHP 5.2
The following is working at my end for PHP 5.3 and 5.2 both.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('log_errors', 0);
class SingleTon {
private static $_controller = null;
private function __construct() {
// do something here or leave it blank.
}
public static function getInstance() {
if (!self::$_controller) {
self::$_controller = new self();
echo "I seem to be working";
}
return self::$_controller;
}
}
$obj = SingleTon::getInstance();
echo "\n";
?>
It displays "I seem to be working". Let me know if you need any further assistance.
Best practice on PHP singleton classes
An example singleton classes in php:
Creating the Singleton design pattern in PHP5 : Ans 1 :
Creating the Singleton design pattern in PHP5 : Ans 2 :
Singleton is considered "bad practice".
Mainly because of this: How is testing the registry pattern or singleton hard in PHP?
why are singleton bad?
why singletons are evil?
A good approach: Dependency Injection
Presentation on reusability: Decouple your PHP code for reusability
Do you need a dependency injection container
Static methods vs singletons choose neither
The Clean Code Talks - "Global State and Singletons"
Inversion of Control Containers and the Dependency Injection pattern
Wanna read more? :
What are the disadvantages of using a PHP database class as a singleton?
Database abstraction class design using PHP PDO
Would singleton be a good design pattern for a microblogging site?
Modifying a class to encapsulate instead of inherit
How to access an object from another class?
Testing Code That Uses Singletons
A Singleton decision diagram (source):
Singleton pattern in php
An example of how you would implement a Singleton pattern for a database class can be seen below:
class Database implements Singleton {
private static $instance;
private $pdo;
private function __construct() {
$this->pdo = new PDO(
"mysql:host=localhost;dbname=database",
"user",
"password"
);
}
public static function getInstance() {
if(self::$instance === null) {
self::$instance = new Database();
}
return self::$instance->pdo;
}
}
You would make use of the class in the following manner:
$db = Database::getInstance();
// $db is now an instance of PDO
$db->prepare("SELECT ...");
// ...
$db = Database::getInstance();
// $db is the same instance as before
And for reference, the Singleton
interface would look like:
interface Singleton {
public static function getInstance();
}
Singleton pattern returns different objects
Actually this is not correct. To implement the singleton pattern correct the constructor has to be protected to prevent the creation of an object with the new operator. The magic methods __clone
and __wakeup
should be private to prevent cloning and unserializing of the object.
If you set the accessibility on these methods like i said, you can get an instance of the singleton object by using the static method getInstance()
which is there for that very reason.
is this how to write a Singleton class for php?
Yes this is a singleton in php. My only edit would be to restrict the clone operation. This can be done by throwing an exception within the __clone magic method
Behaviour of private constructor in singleton design pattern in PHP
You can only initialize it thru Model_Acl::getinstance().
But yes, it will work.
Singleton is not considered a good practice, you should consider Dependency Injection.
http://fabien.potencier.org/article/11/what-is-dependency-injection.
More information about php Singletons
Best practice on PHP singleton classes
Related Topics
Comparing String to Integer Gives Strange Results
How to View Query Error in Pdo PHP
How to Create a Comma-separated List from an Array in PHP
Why Can't I Run Two MySQLi Queries? The Second One Fails
PHP Array Delete by Value (Not Key)
How to Use MySQLi Prepared Statements
Use Global Variables in a Class
How to Catch the Fatal Error: Maximum Execution Time of 30 Seconds Exceeded in PHP
PHP Pass by Reference in Foreach
How to [Recursively] Zip a Directory in PHP
How to Hide Config Files from Direct Access
Angularjs Http Post to PHP and Undefined
Return Single Column from a Multi-Dimensional Array
How to Create Websockets Server in PHP
How to Remove Multiple Utf-8 Bom Sequences