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
// My Singleton Class
class MySingleton
{
// Singleton instance
static private $_instance = null;
// Class Variables
protected $name;
protected function __construct()
{
$this->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();
?>
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
class User
{
public function __construct()
{
// .. Construction code ..
}
}
class CurrentUser extends User
{
static private $_instance = null;
// .. insert code her ..
private function __construct()
{
// .. code here ..
}
static public function GetInstance()
{
if(!self::$_instance)
{
self::$_instance = new User();
}
return self::$_instance;
}
}
$user = CurrentUser::GetInstance();
?>
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
class User
{
public function __construct()
{
// .. Construction code ..
}
}
class CurrentUser
{
// Singleton Instance
static private $_instance = null;
// This class HAS-A user instance
private $user = null;
// .. insert code her ..
private function __construct()
{
// .. constructor code ..
$this->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();
?>
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.
Related Posts
- PHP Design – Biggest Database Oversights Over the last three years I’ve had the opportunity to work on several PHP projects, some of them having grown rapidly and required to scale quickly. Three in particular have been a fantastic learning experience for me. Now I don’t consider myself a total expert, but I thought I would...
- Retrieve Current Module/Controller/Action inside View Script / Layout Script Before I forget to do this again I’m going to make a post on how to get the current Module, Controller, and Action while inside a View Script or Layout Script. Here is the most correct way to do it: Now, here is the incorrect way I attempted to do...
- Page.FindControl() Returning Null Issues and Solutions Within Another Control Alright, I’m going to have a lot of blog posts over the next few days going over my wonderful expereinces learning how to create advanced server controls, and just how hard it is to find good information on the subject. But the problem I ran into today was having Page.FindControl()...
- MySQL – Does Table Exist w/o Throwing Errors There are times where you would like to know if a table exists before executing an query. Most solutions require having MySQL throw an error saying “table does not exist,” but I prefer a cleaner way. I found on this forum post a clean way to do it: This solution...
- Zend Studio vs PHP Development Tools I’ve been using Zend Studio (ZS) for the last two years. It is developed by Zend, the company behind PHP. The very first time I used it and it was able to auto-complete my custom PHP classes I was sold. With version 6 of Zend Studio, they integrated Zend Studio...
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.
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?
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.