Snippet: Singletons with PHP

Today’s snippet describes the singleton pattern. The singleton pattern is a method of creating a class that statically maintains an instance of itself and ensures that no other instances can be created. This is useful for classes that implement app-wide services such as logging, DB access and other shared resources.

The basic requirements for a singleton class are as follows…

  • The constructor is private
    This ensures that nothing outside the class can create instances.
  • A static method exists that returns the instance
    When first called the method creates a statically stored instance of the class. Subsequent calls return the existing instance.
  • Magic methods to prevent the instance from being cloned or serialized (PHP-specific)
    PHP provides functionality to clone and serialize objects. By adding simple implementations of the __clone and __wakeup magic methods we can prevent this from happening.

That’s basically it. Here’s a simple example…

class Singleton
{
  static private $_instance = null;

  public static function & Instance()
  {
    if (is_null(self::$_instance))
    {
      self::$_instance = new self();
    }
    return self::$_instance;
  }

  private function __construct()
  {
    // Do normal instance initialisation here
    // Nothing singleton-related should be present
  }

  public function __destruct()
  {
    // This is just here to remind you that the
    // destructor must be public even in the case
    // of a singleton.
  }

  public function __clone()
  {
    trigger_error('Cloning instances of this class is forbidden.', E_USER_ERROR);
  }

  public function __wakeup()
  {
    trigger_error('Unserializing instances of this class is forbidden.', E_USER_ERROR);
  }

  private $var = '';

  public function SetVar($val)
  {
    $this->var = $val;
  }

  public function GetVar()
  {
    return $this->var;
  }
}

This is an extremely simple example but it demonstrates all of the core concepts. You use this class as follows…

$obj1 = Singleton::Instance();
$obj1->SetVar('some value');

$obj2 = Singleton::Instance();
echo $obj2->GetVar(); // This will echo 'some value'

If you attempt to clone or unserialize an instance your script will fail with an error.

I use this pattern all over the place and definitely recommend using it where it makes sense in your applications. An alternative would be to implement the entire class statically and to be honest I’m not sure whether there are advantages to either implementation. If someone knows please share in the comments.

That’s it for this snippet, stay tuned for more. As always comments, questions, suggestions and requests are welcomed.

Oct 20th, 2008 | Posted in Misc
Tags:
  1. Oct 21st, 2008 at 03:26 | #1

    I rarely ever found myself using “true” singletons in PHP – in most cases, there really isn’t enough of a need to justify the effort.

    You want a single database connection? Make a function called get_db() that returns a local static Database object. That’s better than forcing Database to be a singleton, because it provides additional flexibility (ability to create arbitrary connections, should the need arise) with no obvious drawbacks.

    This is particularly true in a language like PHP, where the scope of any object is at most for a single request.

    In most cases I’ve seen, the desire for a software designer to limit the number of instances of an object boils down to being a control issue, and a mistrust in the discipline of downstream developers. I consider this an issue to solve with education, rather than jumping through hoops in the code (KISS principle).

    But uhh… not that I want to discourage you – I like the list of PHP snippets.

  2. Oct 21st, 2008 at 10:22 | #2

    Thanks for your comment Tom.

    I don’t understand how using a singleton database class is more restrictive than your get_db() function when it comes to creating arbitrary connections. In addition whatever pattern you use can be written with any amount of flexibility you desire. I use a singleton class because it contains a number of helper methods to make certain database operations easier, but it also provides access to the raw resource if required. It also supports multiple connections (read, write, stats) but that’s neither here nor there.

    I also don’t see why the limited life of objects in a PHP request is a factor? I prefer to write well-engineered code regardless of how long each instance will exist. I also prefer maintainable and reusable code, and singletons help me towards those goals in certain situations.

    In regard to not trusting downstream devs, how exactly is a singleton different in that respect from your get_db() function? Aside from that it’s not an issue of trust, it’s a question of the right tool for the job. Singletons are as much about minimising resource usage as they are about anything else. They aid me in creating self-documenting code such that users of my class don’t need a lesson before being able to use it properly.

    But uhh… not that I want to discourage you – I like getting comments. And I’m glad you’re liking these snippets ;) .

  3. Oct 21st, 2008 at 13:39 | #3

    With a singleton, downstream users are programmatically prevented from ever creating more than one instance. However, with the Database example, there’s no real reason to have such a limitation – it’s not physically impossible for many database connections to exist simultaneously. If Database is written as a singleton, then the moment I have to make two connections (e.g. interfacing with any legacy systems, or maybe even a one-time-use script that reads from one, does some conversion, then writes to another), I have to modify the class to support multiple concurrent connections. If Database is a normal class, I just have to create two objects – get_db() only exists to make the usual case easy, and there’s no extra code in there that makes the unusual case hard (including unit-tests that may involve Database construction/destruction).

    Check out http://c2.com/cgi/wiki?SingletonsAreEvi for a discussion on the topic (that wiki is a black hole for free time, seriously).

  4. Oct 21st, 2008 at 13:39 | #4

    Sorry, that last URL should be http://c2.com/cgi/wiki?SingletonsAreEvil

  5. Oct 21st, 2008 at 15:06 | #5

    Tom, I understand your point but I still believe the singleton pattern is a tool worth having in your toolbox. My intention with this post was simply to demonstrate how to implement the singleton pattern in PHP, not to suggest that they should be used where they don’t make sense.

    The only problem you appear to have with the singleton pattern is the requirement for a private constructor. Make it public and your objections go away. For me the pattern is not so much about control than it is about convenience. Everything related to my database connections is taken care of by one class in one file. If I need more flexibility I simply change that one file to bend the way I need it to while maintaining the existing contract so I don’t need to change any other files.

    For most web-based applications a single database connection is the only one that’s needed. In that situation I see no problem using a singleton to manage that connection. If your application needs more than that then a singleton is obviously not the way to go. Likewise with logging as an example, most apps will only need one log so a singleton makes sense there too.

    As I mentioned in my previous comment the project I currently spend most of my time on uses a database class that can manage a number of connections but it’s still controlled. The application begins by making one or more calls to DB::AddConnection() passing all the details required for each connection along with a short name by which it can be referred. Anything that then needs a connection calls DB::Connection() and passes the short name of the connection it wants (read, write, stats, etc) and the class ensures that only one resource for each connection is ever created while providing many useful methods for retrieving and manipulating data.

    In this particular situation a strict singleton pattern was not suitable so I modified it to manage more than one instance. The constructor is still private and all instance management is handled within the class. This meets all my requirements, none of which have anything to do with the trust I have in the developers on my team.

    If you need to be able to create and destroy the database connection for testing purposes all you need to do is add a static method to the class to destroy the singleton instance. Rocket science it ain’t, and for me that requirement is not a good enough reason to avoid the pattern completely.

    If you don’t like the idea of a singleton but still want the advantages the functionality can be duplicated using a modified factory pattern where it knows which objects should be singletons. Personally I prefer to keep information like that inside the class in question. This is effectively what your get_db() function is doing, albeit for a single class.

  6. Dec 1st, 2008 at 21:30 | #6

    I am also using singleton technique. But if you look your code with:

    error_reporting(E_ALL | E_STRICT);

    You will get many many error messages in your code, where you are using this technique.

    Also, if you turn on zend comp. model, you will fail in use singleton.

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>