Creating the Singleton Design Pattern in PHP5

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 Decision Diagram

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



Leave a reply



Submit