Implementing a PHP Singleton
This article describes implementing a singleton class in a PHP application. We assume you're using PHP 5.
Terminology
Singleton
From the book Design Patterns
Intent
Ensure a class only has one instance, and provide a global point of access to it.
Motivation
It's important for some classes to have exactly one instance. Although there can be many printers in a system, there should be only one print spooler...
How do we ensure that the class has only one instance and that the instance is easily accessible?
Make the class itself responsible for keeping track of its sole instance. This is the Singleton pattern.
More info about PHP Singletons
A singleton is a design pattern used to restrict instantiation of a class to one object.
A design pattern is a repeatable solution to a commonly occurring problem in software design.
Implementation
BarberShop is a web forum application that iMarc is building. We are using a singleton to track the current user, the person requesting the page, throughout all the application's objects.
BarberShop uses a number of PHP class files to manage its various objects.
- Post.class.php (Post for short) represents a forum post.
- Reply.class.php (Reply) represents a forum reply to someone's post.
- User.class.php (User) represents a forum user. User's can post and reply in the forum.
There can be multiple posts, multiple replies, and multiple users displayed on each page. A typical page might show a post with 3 replies. Next to each, we see the user's name and avatar.
Handling the current user and his session is a little different.
There can be one, and only one, user requesting a single page. We call this user the current user and many of BarberShop's objects need to know about this person. For example, when viewing a forum post the Post object shows all information making up that post, including pre-filling the reply form with the current user's name and, if the current user is an administrator, printing additional links to edit/delete content.

The current user is represented by an object called CurrentUser. Since Post and Reply and most of the other objects need to know about the current user, you may assume that we're passing that object around from class to class, right? Before we implemented a singleton, we were.
In the alpha version of BarberShop we instantiated CurrentUser in the base class. The base class passed the CurrentUser to all the subclasses.

Here we see a number of subclasses that need to know about the current user. They get fed CurrentUser through their own constructors. This seems like a decent solution...
In this code we also see that Search does not get CurrentUser passed to it. Why, you ask? None of the search methods care if the user is an admin or regular user; nor do they care what the user's name is. Search doesn't need CurrentUser so it doesn't get it.
Our problem begins...
Search does it's searching, gets results, then passes the results to Post or Reply to be displayed properly in the search result list. The Search object instantiates multiple Post and Reply objects to display. Our problem, is that both Post and Reply do need to know about CurrentUser for their displays.
How can we get information about our single, current user from the base class to Search to Post? Remember, Search doesn't use the CurrentUser object internally, but Post does.
Rejected Solution #1

This is not good. Discuss:
Search doesn't use CurrentUser in any of it's internal methods. Therefore, it should not be required to accept CurrentUser in it's constructor only to pass it on to another object.
Rejected Solution #2

This actually isn't a horrible idea, but it's fairly wasteful. When instantiated, CurrentUser has to do some database checks to get the user's info. More important, however, are is the semantic issue:
CurrentUser represents a single, current user, so we shouldn't have multiple instances of the object that represents him.
Singleton Solution


Developer, meet Singleton. Singleton, meet Developer.
See it in action »
And that's how it's done in PHP.
- CurrentUser's constructor is private. From outside the class, $foo = new CurrentUser() doesn't work. Inside the class, in the singleton method, 'new' works fine.
- Because of the private constructor, the 'singleton' method provides the only way to instantiate the class. The singleton method must be a public static method. Public, so it can be called outside the class; static so it retains it's scope.
- The class itself manages its singleness, via the singleton method and private static* class variable, $singleton.
- Subsequent calls to the singleton method (which acts as a constructor or sorts), notice that the $singleton is set, and returns the existing class.
*A static variable exists only in a local scope, but it does not lose its value when program execution leaves this scope.
The Base class, or whichever class calls CurrentUser first, instantiates the singleton CurrentUser. We don't need to pass the singleton object from class to class. When another class instantiates the object, CurrentUser determines if it already exists. If it does, it returns the single object. If not, it instantiates itself and returns the object.
Comments
I like beards.
Another Singleton post. People just got to realize that Singleton is just a nicer way to say $GLOBALS.
Also from the book, Design Patterns: A global variable makes an object accessible, but it doesn't keep you from instantiating multiple objects. Global variables also tend to pollute the name space.
What makes a Singletons different useful it their singleness. If you just instantiated a normal class and made it global, there's nothing stopping another class in your application from instantiating it again.
Beards ARE nice...
They make me look more like a wizened programmer than a 1337 h@x0r despite my untucked shirt and baggy jeans...
This of course, being good for the suits that sign my paycheck :-)
Dave, I assume you've simplified CurrentUser for the purpose of this example. For example, I would expect your class hierarchy includes a User class from which CurrentUser is derived.
Another nit-picky detail from the software engineer in me: should you _really_ receive the same object when you pass a different value for $database to the singleton method?
Jeff, yes everything has been simplified for the example. I probably should have removed all the $database references as well.
Since this writing, the code has been updated. Now, only the base class receives the Database object through it's constructor. It no longer needs to pass $database around to the other classes.
By the way, are you from Newburyport, MA? (your newburyportion.com site is nice!) We're in downtown NBPT.
Yep, I'm right across the street: just upstairs from the Pumpkin Patch. I ran into Rob Mohns while walking my cat in the park. I've been following the "adventures" of my hometown Web developers with some interest. It's nice to see that Newburyport has more to it than just tourists.
Hi ,
I'm Niro, a student from sri lanka. I am stuck with some php problem. I hope you can help me with this. I'm using singleton design pattern. But im stuck with a problem.
the application is something like this.
using singleton when he enters my account page he is instanciated a logger class instance. object is created. Now its working fine.
$log = Logger::getInstance(); $log->Log(5); echo "{$log->user->getUserTable()}"; $_SESSION['logger'] = serialize($log);
then for me i need this class object to take in the session. so what i did was serialize the object and unserialize from my next page to the same object name to retrieve it. then i call getInstance method.
$blob = unserialize($_SESSION['logger']);
$blob = Logger::getInstance();
echo "{$blob->user->getUserTable()}";
But friend it build a new Logger instance who has an attribute called guest not the member (where i have given from the earlier page) . Means it still don't recognize the same object as its getInstance(). Pls tell help me to find a solution.
Tony how does the singleton design theory really apply when you use sessions. how do we carry the object instantiated from one page and in the next page recognize as the same object. Pls reply me as soon as possible. Thank you very much.
Read something more recent.
Statements and opinions expressed in this blog and any comments made are the private opinions of the respective poster, and, as such, iMarc LLC is neither responsible nor liable for such content.
Visitors
I too have found Singletons to be HIGHLY useful.
In trying to develop a straight forward design pattern for object oriented authenticated applications I spent much time examining the patterns in the book PHP 5 Objects, Patterns, and Practice by Matt Zandstra (http://www.apress.com/book/bookDisplay.html?bID=358).
I highly recommend it.
I think I'm currently in the 2nd or third stage of new idea adoption though, as I have been guilty of using a Singleton where it really wasn't the best choice :-)