We recently had a discussion if it was possible to build a trait Singleton
PHP Traits and we played around with it a possible Implementation but ran into issues with building one.
This is an academic exercise. I know that Singletons have very little - if not to say no - use in PHP
and that one should 'just create one'
but just for exploring the possibilities of traits:
<?php
trait Singleton
{
protected static $instance;
final public static function getInstance()
{
return isset(static::$instance)
? static::$instance
: static::$instance = new static;
}
final private function __construct() {
static::init();
}
protected function init() {}
final private function __wakeup() {}
final private function __clone() {}
}
class A {
use Singleton;
public function __construct() {
echo "Doesn't work out!";
}
}
$a = new A(); // Works fine
reproduce: http://codepad.viper-7.com/NmP0nZ
The question is: It is possible to create a Singleton Trait in PHP?
A bit late to the party, but I wanted to show how (in Eclipse Oxygen PDT at least) you can do the DocBlock where auto-completion will work for this
As you can see both
$instance
andgetInstance
are defined asself
. Eclipse is smart enough to work this out so that when you use it in a class all the auto-completion works just as normal.Test
This is guys all what you need. If you wish you could use private static member, but there is no a real need... Tested, works despite the fact that you might think that static will be global or something :)
usage:
The thing is that the type of getInstance return will be ambigous since it depends on the consumer. This gives a weak-typed method signature. For instance it makes it impossible to provide an @return in compliance with the consumer type in the getInstance method doc bloc.
Quick solution we've found (thanks chat!):
If a trait and a class both define the same method, the one of class if used
So the Singleton trait only works if the class that uses it doesn't define a
__construct()
Trait:
Example for a consuming class:
The var_dump now produces the expected output:
and the new fails:
Demo
I created one a while ago when i was bored trying to learn traits. It uses reflection and the
__CLASS__
constantTrait:
This way you can continue to use the __construct() method and don't need to use an arbitrary function as the constructor.