PHP Singletons, Sub-Classing, and HAS-A Relationships

I’ve been very busy these last fews weeks and have neglected making any posts. While there are a variety of subjects I’d love to post about, they’ll most likely have to wait until the next year. However, I thought I might be able to throw up a quick example of how to use PHP Singletons and extending public classes.

The Singleton Pattern “is a design pattern that is used to restrict instantiation of a class to one object.” (Wikipedia) In PHP, a singleton is created by making the constructor protected or private. “How do you create an object then?” Its done in two parts. First, you make a static class variable that is private, to hold the instance. Second, create a static function to return the instance. Here is an example:

[php]
name = ‘John’;
}

static public function GetInstance()
{
// Check to see if the instance is null
if(!self::$_instance)
{
self::$_instance = new MySingleton();
}

return self::$_instance;
}

public function GetName()
{
return $this->name;
}
}

// Use the Singleton Class
$class = MySingleton::GetInstance();
echo “Hello, my name is: “.$class->GetName();

// Or you can call the function this way:
echo “Hello, my name is: “.MySingleton::GetInstance()->GetName();
?>
[/php]

Singletons can be create if you need only one instance of a class. You must be careful, however, because you don’t want to “lock” yourself into an implementation where you really need more than one instance.

Now, what if I want to have a singleton of a current class? Let me give you an example. I have a project with a User class. Its used all over the website for display user’s information. Now, I wanted to create a class called CurrentUser, which is a singleton that holds the instance for the currently logged in user. Why would I want to do this? Once I get a user’s information, I only want to have to retrieve it once. I was running into problems where different parts of the website would request the current user’s information over, and over.

So at first I tried to sub-class the User class. Something like this:

[php]

[/php]

There is only one problem: when I tried to declare the constructor private, it threw an error:

Fatal error: Access level to CurrentUser::__construct() must be public (as in class User) in /path/to/file.php on line 73

The problem is you can’t protect or privatize a public function. If a parent has a less restrictive function, it’s child cannot make it more restrictive. But with a singleton, the pattern’s goal is to restrict the construction of an object to ensure only one instance. So how do we overcome this problem? HAS-A relationship, instead of a IS-A.

HAS-A relationship uses class members instead inheritance to accomplish it’s design. Whats the difference? Instead of CurrentUser “being” a sub class of User, it “has” a member variable containing an instance of a User object. We then don’t have to worry about overriding the constructor. Here is how you could do it:

[php]
user = new User();

}

static public function GetInstance()
{
if(!self::$_instance)
{
self::$_instance = new CurrentUser();
}

// Instead of returning the singleton instance, return it’s user instance
return self::$_instance->user;
}
}

$user = CurrentUser::GetInstance();

?>
[/php]

Nifty how that works. As developers, its easy to think “sub-classing” is the best method. It feels very “OOP” and it works in many ways. However, many times our design in the long run is much more complicated than sub-classing can handle. HAS-A relationships can offer more flexibility in the long run. Hopefully this can help out some people, and give others an idea on how to make Singletons work for you.

3 thoughts on “PHP Singletons, Sub-Classing, and HAS-A Relationships

  1. Good stuff! Well written up, I’ve used a “registry” class in the past so I could store all kinds of data in one class rather than have lots of classes that effectively do nothing, but I guess both methods have their plus points.

    Like

  2. I dont think that “static private $_instance = null;” is good idea. Why is private for, if you could access from outside, like self::$_instance? It’s not private then. Why you are not using $_instance variable as static in your GetInstance function?

    Like

  3. Thanks for the question Timmy.

    The reason for “static private $_instance” is for several reasons.

    First, I declare it static so that the variable is the same across any and all instances of this class. It is important because I use a static method to retrieve this value. Static methods do not have access to “$this”.

    Second, the private is to ensure that the only manipulation done to the $_instance variable is by the CurrentUser class. By declaring it private, only functions withint the CurrentUser class have access to it. Outside I couldn’t do “CurrentUser::$_instance;” to retrieve the object. You only can access it through the GetInstance function. This helps safe-guard against developers on accidentally breaking functionality.

    I hope this helps.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this:
search previous next tag category expand menu location phone mail time cart zoom edit close