Implementing a PHP Singleton
by Dave Tufts - November 9, 2006 / 5:03pm View more articles
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 have been turned off on this blog.
Read something more recent.
9 Comments
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 :-)
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.
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 :-)
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?
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.
"; $_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.