Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why people use singletons in their PHP framework

Ok guys I am struggling to understand why there is a need of singleton.

Let's make a real example: I have a framework for a my CMS
I need to have a class that logs some information (let's stick on PHP).

Example:

class Logger{
   private $logs = array();

   public function add($log) {
      $this->logs[]=$log;
   }      
}

Now of course this helper object must be unique for the entry life of a page request of my CMS.
And to solve this we would make it a singleton (declaring private the constructor etc.)

But Why in the hell a class like that isn't entirerly static? This would solve the need of the singleton pattern (that's considered bad pratice) Example:

class Logger {
    private static $logs = array();

    public static function add($log) {
        self::$logs[]=$log;
    }
}

By making this helper entirely static, when we need to add a log somewhere in our application we just need to call it statically like: Logger::add('log 1'); vs a singleton call like: Logger::getInstance()->add('log 1');

Hope someone makes it easy to understand for me why use singleton over static class in PHP.

Edit

This is a pretty nice lecture on the singleton vs static class for who is interested, thanks to @James. (Note it doesn't address my question)

like image 299
dynamic Avatar asked May 15 '11 23:05

dynamic


People also ask

What is the purpose of singletons?

The Singleton's purpose is to control object creation, limiting the number to one but allowing the flexibility to create more objects if the situation changes. Since there is only one Singleton instance, any instance fields of a Singleton will occur only once per class, just like static fields.

Why you should not use singletons?

By using singletons in your project, you start to create technical debt. Singletons tend to spread like a virus because it's so easy to access them. It's difficult to keep track of where they're used and getting rid of a singleton can be a refactoring nightmare in large or complex projects.


5 Answers

Many reasons.

Static methods are basically global functions that can be called from any scope, which lends itself to hard to track bugs. You might as well not use a class at all.

Since you cannot have a __construct method, you may have to put an init static method somewhere. Now people in their code are unsure if the init method has been called previously. Do they call it again? Do they have to search the codebase for this call? What if init was somewhere, but then gets removed, or breaks? Many places in your code now rely on the place that calls the init method.

Static methods are notoriously hard to unit test with many unit testing frameworks.

There are many more reasons, but it's hard to list them all.

Singletons aren't really needed either if you are using DI.

A side note. DI allows for your classes not to rely on each other, but rather on interfaces. Since their relationships are not cemented, it is easier to change your application at a later time, and one class breaking will not break both classes.

There are some instances where single state classes are viable, for instance if none of your methods rely on other methods (basically none of the methods change the state of the class).

like image 134
dqhendricks Avatar answered Oct 03 '22 08:10

dqhendricks


I use singletons, so I can tell you exactly why I do it instead of a static function.

The defining characteristic of a singleton is that it is a class that has just one instance. It is easy to see the "just one instance" clause and forget to see the "it is a class" clause. It is, after all, a normal class object with all the advantages that that brings. Principly, it has its own state and it can have private functions (methods). Static functions have to do both of these in more limited or awkward ways.

That said, the two complement each other: a static function can be leveraged to return a singleton on the same class. That's what I do in the singleton I use the most often: a database handler.

Now, many programmers are taught that "singletons are bad, mm'kay?" but overlook the rider that things like are usually only bad when overused. Just like a master carver, an experienced programmer has a lot of tools at his disposal and many will not get a lot of use. My database handler is ideal as a singleton, but it's the only one I routinely use. For a logging class, I usually use static methods.

like image 33
staticsan Avatar answered Oct 03 '22 10:10

staticsan


Singletons allow you to override behavior. Logger::add('1') for example can log to different devices only if the Logger class knows how. Logger::getLogger()->add('1') can do different things depending on what subtype of Logger getLogger() returns. Sure you can do everything within the logger class, but often you then end up implementing the singleton inside the static class.

like image 34
leblonk Avatar answered Oct 03 '22 10:10

leblonk


If you have a static method that opens a file, writes out and closes it, you may end up with two calls trying to open the same file at the same time, as a static method doesn't guarantee there is one instance.

But, if you use a singleton, then all calls use the same file handler, so you are always only having one write at a time to this file.

You may end up wanting to queue up the write requests, in case there are several, if you don't want them to fail, or you have to synchronize in other ways, but all calls will use the same instance.

UPDATE:

This may be helpful, a comparison on static versus singleton, in PHP.

http://moisadoru.wordpress.com/2010/03/02/static-call-versus-singleton-call-in-php/

like image 38
James Black Avatar answered Oct 03 '22 08:10

James Black


As leblonk mentioned, you can't override static classes, which makes unit testing very difficult. With a singleton, you can instantiate a "mock" object instead of the actual class. No code changes needed.

Static classes can have namespace conflicts. You can't load 2 static classes of the same name, but you can load 2 different versions of a singleton and instantiate them under the same name. I've done this when I needed to test new versions of classes. I instantiate a different version of the class, but don't need to change the code that references that class.

I often mix singletons and static. For example, I use a database class that ensures there is only 1 connection to each master (static) and slave (singleton). Each instance of the db class can connect to a different slave, if a connection to the same slave is requested, the singleton object is returned. The master connection is a static object instantiated inside each slave singleton, so only 1 master connection exists across all db instantiated objects.

like image 27
Brent Baisley Avatar answered Oct 03 '22 10:10

Brent Baisley