I'm working in a web app framework, and part of it consists of a number of services, all implemented as singletons. They all extend a Service class, where the singleton behaviour is implemented, looking something like this:
class Service {
protected static $instance;
public function Service() {
if (isset(self::$instance)) {
throw new Exception('Please use Service::getInstance.');
}
}
public static function &getInstance() {
if (empty(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
}
Now, if I have a class called FileService implemented like this:
class FileService extends Service {
// Lots of neat stuff in here
}
... calling FileService::getInstance() will not yield a FileService instance, like I want it to, but a Service instance. I assume the problem here is the "self" keyword used in the Service constructor.
Is there some other way to achieve what I want here? The singleton code is only a few lines, but I'd still like to avoid any code redundance whenever I can.
Use trait instead of a abstract class allows to extend a singleton class.
Use the trait SingletonBase for a parent singleton class.
Use the trait SingletonChild for its singleton childs.
Had I paid more attention in 5.3 class, I would have known how to solve this myself. Using the new late static binding feature of PHP 5.3, I believe Coronatus' proposition can be simplified into this:
I tried it out, and it works like a charm. Pre 5.3 is still a whole different story, though.
I have found a good solution.
the following is my code
You can refer http://php.net/manual/en/language.oop5.late-static-bindings.php for more info
This is fixed Johan's answer. PHP 5.3+
Code:
If you use PHP < 5.3, add this too: