I want to define a Singleton base type from which the user will derive his classes, so this is what I thought:
interface SingletonInterface {
public static function getInstance();
}
abstract class SingletonAbstract implements SingletonInterface {
abstract protected function __construct();
final private function __clone() {}
}
But using this aproach the user may implement this singleton...
class BadImpl implements SingletonInterface {
public static function getInstance() {
return new self;
}
}
What would be your aproach?
Remember PHP doesn't allow multiple inheritance so you must carefully choose what you base your classes on. Singleton is so easy to implement it's probably better to let each class define it.
Beware also that private fields are not ported to descendant classes and therefore you can have two different fields with the same name.
I am using this code for creating a Singleton:
abstract class Singleton {
private static $_aInstance = array();
private function __construct() {}
public static function getInstance() {
$sClassName = get_called_class();
if( !isset( self::$_aInstance[ $sClassName ] ) ) {
self::$_aInstance[ $sClassName ] = new $sClassName();
}
$oInstance = self::$_aInstance[ $sClassName ];
return $oInstance;
}
final private function __clone() {}
}
This is using of this pattern:
class Example extends Singleton {
...
}
$oExample1 = Example::getInstance();
$oExample2 = Example::getInstance();
if(is_a( $oExample1, 'Example' ) && $oExample1 === $oExample2){
echo 'Same';
} else {
echo 'Different';
}
First of all: if you have so much Singletons over the project then you probably mess up something on projection level
Second of all: Singleton should be used there, and only there, where more that one instance of a class makes totally no sense or might cause some errors
Finally: the inheritance ain't designed to reduce the amount of code
You can now use traits, but do you need so much singletons ?
Related
Straight to the point:
I've got two singleton classes, both inheriting their singleton nature from a super-class. I initialize some properties on the first singleton, and then have the second singleton retrieve the instance of the first one. That instance, however, does not seem to be the one I initialized in the first place. Some example code might help to explain this:
First, the super-class, providing singleton nature (requires PHP 5.3 or greater):
class Singleton {
protected static $instance;
protected function __construct() { }
final private function __clone() { }
public static function getInstance() {
if (!(static::$instance instanceof static)) {
static::$instance = new static();
}
return static::$instance;
}
}
Then we've got the the first singleton carrying a value:
require_once('Singleton.php');
class SingletonA extends Singleton {
protected $value;
public function SingletonA() {
$this->value = false;
}
public function getValue() {
return $this->value;
}
public function setValue($value) {
$this->value = $value;
}
}
Then the second singleton that references the first singleton:
require_once('Singleton.php');
require_once('SingletonA.php');
class SingletonB extends Singleton {
public function getValue() {
return SingletonA::getInstance()->getValue();
}
}
Now for the test that shows how this fails:
require_once('SingletonA.php');
require_once('SingletonB.php');
SingletonA::getInstance()->setValue(true);
echo (SingletonA::getInstance()->getValue()) ? "true\n" : "false\n";
echo (SingletonB::getInstance()->getValue()) ? "true\n" : "false\n";
The test yields the following output:
true
false
Clearly, the SingletonA instance that the test code references is not the same instance that the SingletonB instance references. In short, SingletonA is not as single as I need it to be. How is this possible? And what magic can I wield to remedy this behaviour, giving me a true singleton?
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];
}
}
SingletonA and SingletonB are different classes. Although they inherit from the same class, they are separate classes and so they have different static instances.
If you change your code to get 2 instances of SingletonA or 2 instances of SingletonB, you will see the behavior you expect. But because they are different classes, they are not the same singleton.
I'm pretty sure it's because you are using static methods, which are not instanced.
Let's talk OO. :)
SingletonA and SingletonB are of type Singleton
thus it can be said:
SingletonA is Singleton
and
SingletonB is Singleton
i.e. they're both Singleton
The expected meaning of Singleton means there can be only one. Many people from an OO background using your code will be confused.
Usually, implementation of Singleton would be on a per class basis because most OO languages will not be bent to allow the intent of what you are proposing.
That PHP might do (via get_called_class() magic) doesn't mean it should.
I can absolutely accept that from a utilitarian point of view, the accepted answer looks good. Given the niftyness of the accepted answer, I'd propose a name change that doesn't conflict with "standard" Singleton implementation. From a strict OO point of view, one could never inherit from a Singleton, so it really needs a different name.
Let's imagine that we have Registry pattern...
<?php
class Registry
{
private static $objects = array();
private static $instance = null;
public static function getInstance() {
if (self::$instance == null) {
self::$instance = new Registry();
}
return self::$instance;
}
protected function _get($key) {
return ($this->objects[$key]) ? $this->objects[$key] : null;
}
protected function _set($key, $val) {
$this->objects[$key] = $val;
}
public static function get($key) {
return self::getInstance()->_get($key);
}
public static function set($key, $object) {
return self::getInstance()->_set($key, $object);
}
}
?>
Using this realization is really easy...
<?
Registry::set('db', $db_client);
Registry::set('redis', $redis_client);
//Using registered objects is really easy
Registry::get('db')->query("...");
Registry::get('redis')->get("...");
?>
But as you can see, we're adding instances into registry even if we don't need them (yes, it's all about performance).
So, the question is... How to modify Registry pattern to be able to do lazy instantiation?
Here is what I'm looking for...
<?
class Registry
{
private static $objects = array();
private static $instance = null;
public static function getInstance() {
if (self::$instance == null) {
self::$instance = new Registry();
}
return self::$instance;
}
protected function _db() {
if (!$this->objects['db']) {
$this->objects['db'] = new DatabaseAdapter(DB_HOST, DB_NAME, DB_USER, DB_PASSWORD);
}
return $this->objects['db'];
}
protected function _redis() {
if (!$this->objects['redis']) {
$this->objects['redis'] = new Redis(REDIS_HOST, REDIS_DB, REDIS_USER, REDIS_PASSWORD);
}
return $this->objects['redis'];
}
public static function db() {
return self::getInstance()->_db();
}
public static function redis() {
return self::getInstance()->_redis();
}
}
?>
As you can see, DatabaseAdapter() or Redis() will be created only in we'll request them. Everything seems to be ok, but as you can see it's not a standalone class because _db(), _redis() methods contains connection constants etc.
How to avoid it? How can I define registry method within registry class to separate Registy class and objects inside it?
I'm really sorry about my English, but I hope it is clear for you.
Thank you.
PS: All code above was written 1 min. ago and wasn't tested.
If you use global constants you will always have a dependency on the global scope. It doesnt matter where it is. Also, even if you do not use constants, you still have the dependency on the Database class inside the Registry. If you want to dissolve those dependencies, you could use Factory methods on the to be created classes:
public function get($service)
{
if( !this->_data[$service] ) {
// requires PHP 5.2.3
this->_data[$service] = call_user_func($service .'::create');
}
return this->_data[$service];
}
So if you do get('DB'), the code would try to call the static DB::create() method inside the class you intend to create. But like I said, if you use global Constants for the configuration, you would just move the problem into another class.
Your db class could look like this:
class DB
{
protected static $_config;
public static setConfig(array $config)
{
self::_config = $config;
}
public static create()
{
return new self(
self::config['host'],
self::config['db'],
self::config['user'],
self::config['pass']);
}
}
The configuration can be stored inside an external configuration file, which you load and set to the DB class during bootstrap, e.g.
DB::setConfig(parse_ini_file('/path/to/db-config.ini'));
The disadvantage of this is, you have to add create() methods all over the place and all classes must be able to store their own configuration. You could centralize these responsibilities into a Builder pattern. But if you do this, you are half way to implementing an IoC Container anyways, so check out the following resources:
Fabien Potencier: What is Dependency Injection
Martin Fowler: Inversion of Control Containers and the Dependency Injection pattern
Design pattern – Inversion of control and Dependency injection
Note: You are using a "static" modifier for $objects - as you are working with an instance, this is probaby not necessary.
How can I define registry method within registry class to separate Registy class and objects inside it?
They are always separate: Each object inside the registry class is just a reference to the (independent) object. But if this question is about including the appropriate class definition (?) you may use the class_exists() function to load the class as soon as required.
BurninLeo
I have always used a Singleton class for a registry object in PHP. As all Singleton classes I think the main method looks like this:
class registry
{
public static function singleton()
{
if( !isset( self::$instance ) )
{
self::$instance = new registry();
}
return self::$instance;
}
public function doSomething()
{
echo 'something';
}
}
So whenever I need something of the registry class I use a function like this:
registry::singleton()->doSomethine();
Now I do not understand what the difference is between creating just a normal static function. Will it create a new object if I just use a normal static class.
class registry
{
public static function doSomething()
{
echo 'something';
}
}
Now I can just use:
registry::doSomethine();
Can someone explain to me what the function is of the singleton class. I really do not understand this.
A static function is a function that can be called without creating an object of a class.
registry::doSomething()
A Singleton is a design pattern, that should prevent the users of the class from creating more than one instance of a class. So, there is usually only one instance of a singleton class. A Singleton's constructor should be declared private and have a static method providing a single instance-object:
class Singleton
{
private Singleton()
{
}
private static var $instance = null;
public static getInstance()
{
if(self::$instance == null)
self::$instance = new Singleton();
return self::$instance;
}
}
For more information see http://en.wikipedia.org/wiki/Singleton_pattern
P.S: Sorry for my bad PHP, the syntax may not be 100% correct, but you should roughly understand what I mean in terms of OOP.
The fact that the Singleton is a design-pattern that restricts instantiation of a class to one single object, it is possible to do some stuff that is slightly more difficult with a static class:
Lazy initialization
Replace implementation internally by sub-classing the Factory
Manage via configuration
However, there are several drawbacks to singletons, so it is better in general to use patterns such as Factory as you get additional benefits such as decoupling.
When creating a Singleton in PHP, I ensure that it cannot be instantiated by doing the following:
class Singleton {
private function __construct() {}
private function __clone() {}
public static function getInstance() {}
}
However, I realised that defining a class as 'abstract' means that it cannot be instantiated. So is there anything wrong with doing the following instead:
abstract class Singleton {
public static function getInstance() {}
}
The second scenario allows me to write fewer lines of code which would be nice. (Not that it actually makes much of a difference.)
When creating a singleton in PHP, declaring the __construct and __clone as private ensures that the class cannot be instanciated from the outside : it can still be instanciated from inside its declaration.
When declaring a class as abstract, it can not be instanciated at all ; not even from inside its declaration.
This means your solution would not work : in the second case, your getInstance() method will not be able to instanciate the class -- while it can do so in the first case.
No because then then you can't instantiate the class at all (not even in the static getInstance method). The private constructor in the singleton example just assures, that only the static getInstance method from the same class can access the constructor.
No, you cannot use an abstract class instead of a private __construct() when creating a singleton. But if your intention is to create an Abstract Singleton from which to extend from, you can do so like this:
abstract class Singleton
{
private static $_instances;
public static function getInstance()
{
$className = get_called_class(); // As of PHP 5.3
if(! isset(self::$_instances[$className] )) {
self::$_instances[$className] = new $className();
}
return self::$_instances[$className];
}
protected function __construct( ) {}
final private function __clone( ) {}
final private function __wakeup( ) {}
}
You can then extend from Singleton like this:
class Foo extends Singleton {
protected $_foo = 1;
public function setFoo($i) { $this->_foo = $i; }
public function getFoo() { return $this->_foo; }
}
and
class Bar extends Singleton {
protected $_foo = 1;
public function setFoo($i) { $this->_foo = $i; }
public function getFoo() { return $this->_foo; }
}
and manipulating:
$foo1 = Foo::getInstance();
$foo1->setFoo(5);
$foo2 = Foo::getInstance();
var_dump($foo2);
$bar1 = Bar::getInstance();
var_dump($bar1);
echo new ReflectionObject($foo2);
echo new ReflectionObject($bar1);
However, keep in mind that Singletons are very hard to unit-test and should be avoided if possible. See my answer here for some background:
How to remove multiple instances and just have one instance while multiple function calls in php?
Is there a use-case for singletons with database access in PHP?
It could work if your Singleton::getInstance() is supposed to return an instance of a different class.
abstract class Singleton {
public static function getInstance() {
static $instance = null;
if ( is_null($instance) ) {
$instance = new StdClass; // a different class than 'abstract class Singleton'
$instance->x = time();
}
return $instance;
}
}
$obj = Singleton::getInstance();
But I'd find that confusing. A bit like misusing abstract to combine the complexity of an abstract factory with the restraints of a singleton.
UPDATE: Rephrasing the question to ask, 'are there too many' static methods (I realize that right now there are only 4 but I originally started with 2) in this class structure? If so, any suggestions on how to refactor these classes to use some sort of Finder class so that I can remove the static functions from the Model classes?
I have the following abstract class:
abstract class LP_Model_Abstract
{
protected static $_collectionClass = 'LP_Model_Collection';
protected $_row = null;
protected $_data = array();
public function __construct($row = null)
{
$this->_row = $row;
}
public function __get($key)
{
if(method_exists($this, '_get' . ucfirst($key)))
{
$method = '_get' . ucfirst($key);
return $this->$method();
}
elseif(isset($this->_row->$key))
{
return $this->_row->$key;
}
else
{
foreach($this->_data as $gateway)
{
if(isset($gateway->$key))
{
return $gateway->$key;
}
}
}
}
public function __set($key, $val)
{
if(method_exists($this, '_set' . ucfirst($key)))
{
$method = '_set' . ucfirst($key);
return $this->$method($val);
}
elseif(isset($this->_row->$key))
{
$this->_row->$key = $val;
return $this->_row->$key;
}
else
{
foreach($this->_data as $gateway)
{
if(isset($this->_data[$gateway]->$key))
{
$this->_data[$gateway]->$key = $val;
return $this->_data[$gateway]->$key;
}
}
}
}
public function __isset($key)
{
return isset($this->_row->$key);
}
public function save()
{
$this->_row->save();
}
abstract public static function get($params);
abstract public static function getCollection($params = null);
abstract public static function create($params);
}
And then this class which provides additional functionality for class table inheritance schemes (where type is important in determining additional functionality in a factory fashion):
abstract class LP_Model_Factory_Abstract extends LP_Model_Abstract
{
protected static $_collectionClass = 'LP_Model_Collection_Factory';
abstract public static function factory($row);
}
These ultimately result in the following type of class declaration:
class Model_Artifact extends LP_Model_Factory_Abstract
{
protected static $_artifactGateway = 'Model_Table_Artifact';
public static function create($params)
{
}
public static function get($params)
{
$gateway = new self::$_artifactGateway();
$row = $gateway->fetchArtifact($params);
return self::factory($row);
}
public static function getCollection($params = null)
{
$gateway = new self::$_artifactGateway();
$rowset = $gateway->fetchArtifacts($params);
$data = array(
'data' => $rowset,
'modelClass' => __CLASS__
);
return new self::$_collectionClass($data);
}
public static function factory($row)
{
$class = 'Model_Artifact_' . $row->fileType;
}
}
When do you know that you have too many static methods in a class? And how would you refactor the existing design so that the static methods are perhaps encapsulated in some sort of Finder class?
I'd have to agree with Brubaker and add that to my thinking it isn't the number of methods so much as the functionality of said methods. If you start thinking that your class has to many methods (static or otherwise) then you might find they can be re-grouped and refactored into a more intuitive architecture.
The first indicator I use when determining if I have to many static methods is if the methods functionality is not stateless. If the static methods change the state of the object they reside in, they probably shouldn't be static.
I agree with BaileyP and I'll add my couple of pennies:
I always work with the idea that a class should have a single reason for existing; it should have one job that it does, and it should do it well. After deciding that, and figuring out what the interface to that class should be, I go through and mark any functions that don't change the state of an instance of the class as static.
If you want to build reusable and testable code, you should avoid static methods altogether. Code which calls static methods (or constructors of non-data-like classes) cannot be tested in isolation.
Yes, you will have to pass around alot more objects if you eliminate static methods. This is not necessarily a bad thing. It forces you to think about the boundaries and cooperation between your components in a disciplined way.
Personally I find that any number of static methods are a sign of trouble. If your class has instance methods and static methods, then most likely you could split the class into two separate entities and change the static methods to instance methods.
Think of a class as a special kind of object, with the distinctive property that it is global by nature. Since it's a global variable, it implies a very strong level of coupling, so you would want to reduce any references to it. Static members will need to be referred, meaning that your code will get a strong level of coupling to the class.
I'll throw in my 2 cents.
First of all, I'll agree that setting some sort of arbitrary limit is not helpful, such as "Once I have more than 10 statics in a class that's too many!". Refactor when it makes sense but don't start doing it just because you've hit some imaginary boundary.
I wouldn't 100% agree with Brubaker's comment about stateful vs. stateless - I think the issue is more about classes vs instances. Because a static method can change the value of another static property which is a stateful change.
So, think of it like this - if the method/property is of or pertaining to the class, then it should probably be static. If the method/property is of or pertaining to an instance of the class, it should not be static.