iMarc | Interactive Media Architects
  • Portfolio
  • Process
  • About
  • Communiqué
  • Contact
  • Support
  • Search

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.

Code Example 1

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.

Code Example 1

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

In BarberShop.class.php, pass CurrentUser to the Search object, so Search can pass it on to Reply and Post.

Code Example 2

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

Don't pass CurrentUser to any of the subclasses. instantiate a new CurrentUser object in each subclass that needs it.

Code Example 3

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

Code Example 4, The Singleton

Code Example 5

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.

More Articles Get the RSS Feed Post A Comment

9 Comments

by Errol Sayre   #
on November 10, 2006 / 9:32am
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 :-)
by Fred LeBlanc   #
on November 10, 2006 / 9:34am
I like beards.
by Oh great   #
on November 10, 2006 / 9:49am
Another Singleton post. People just got to realize that Singleton is just a nicer way to say $GLOBALS.
by Dave Tufts   #
on November 10, 2006 / 10:07am
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.
by Errol Sayre   #
on November 10, 2006 / 3:50pm
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 :-)
by Jeff Watkins   #
on November 20, 2006 / 7:34am
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?
by Dave Tufts   #
on November 20, 2006 / 8:25am
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.
by Jeff Watkins   #
on November 20, 2006 / 7:31pm
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.
by nirosha   #
on August 7, 2007 / 4:01am
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.

Comments have been turned off on this blog.
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.

iMarc

iMarc is a web development company in Newburyport, MA. This is our blog.
View all blogs or learn more about iMarc.

About the Author

Dave's Head Dave Tufts, Vice President of Technology
I help people build websites.
I have two daughters.
I'd rather be gardening.
More blogs by Dave

Search Our Blog

Recent Communiqués

  • Inc. 5000
  • Say Hello to our new Sys Admin
  • "Not Invented Here" for a Triple Word Score
  • ca·coph·o·ny
  • Clank
  • Year in Quotes (volume 2)
  • Gunslinging Rockstar Ninjas
  • Now Hiring: Junior Interactive/Web Designer
  • Photoshop: Create Your Own Glossy Icons
  • They only come out at night
  • Context switches are expensive
  • <i> is not evil.
  • Schooled.
  • Full-screen branding
  • Summer Job, iMarc Style

Popular Communiqués

  • Now Hiring: Junior Interactive/Web Designer
  • Photoshop: Create Your Own Glossy Icons
  • Say Hello to our new Sys Admin
  • "Not Invented Here" for a Triple Word Score
  • ca·coph·o·ny
  • Custom Away Messages are Overrated
  • Summer Job, iMarc Style
  • They only come out at night

Recent Comments

  • Inc. 5000

    By Nick: Congrats.

  • Inc. 5000

    By Craig Henry: WOOWOOOO

  • Inc. 5000

    By Jeff Turcotte: wow!!

  • Photoshop: Create Your Own Glossy Icons

    By nicole: thats cool ,but can u make it a little easyer . =/…

  • Say Hello to our new Sys Admin

    By Nick: 14 days and no love. Congrats Mike.

RSS

RSS Icon Learn about RSS and get the feed for our blog.

About iMarc

  • We build custom web sites
  • In-house strategy, design, programming, hosting
  • In business since 1997
  • We’re located in Newburyport, MA
  • Call us at (978) 462-8848

© 2008 iMarc LLC, Contact Us

Links

  • Home
  • Portfolio
  • Client Support
  • Log In
  • (icon)RSS

Meet the Team

Robert's Head Robert Mohns, Information Architect

Will architect websites for Wii.

Learn More | Meet the Others