Subscribe to Martyr2's Programming Underground        RSS Feed
-----

Introduction to the Singleton Pattern in PHP

Icon 9 Comments
Ok, what the hell is with all this talk about design patterns? The bookstore has books dedicated to the subject, experts in all the different computer language fields are talking about them, and how the hell does it make my programming life easier? The answers may be "They are gossips", "Authors have nothing else to write about", and "Yes they will make things a bit easier for you in the way of programming". So lets start with a simple one on this entry of the Programmer's Underground!

<Cartoon network on shrooms version of the theme music>

If you have ever gone to chapters or barnes and noble bookstores you may have seen books on "Design patterns" for any given language or a book on it completely on its own. You might have even picked it up and saw some kind of complex discussion on how these patterns will revolutionize the way programming is done in large scale projects or how it can do everything including get your kids ready for school, make their lunch, and even drive them there while you sleep in. I will be the first to tell you that they are not fabulous wonderous super kick ass code modules that will save the world. They are however very cool and can save you a bit of time, code redundancy, and having to decipher that mess of complexity which is project code.

We will discuss one of the more simplistic of all the patterns and show you that they don't have to be incredibly complex to understand and use. Once you got the idea under your belt you will be ready to go and most likely remember it for your next project. Then you can whip out witty comments to your co-workers like "You know, we could simplify this with a singleton pattern here and cut out all this garbage here, making it more elegant." Then you know, you may go on to have that lavished quarter million dollar a year job where everyone in the software world will idolize you. That or your boss will give you a pat on the back, take all the credit, and you can get your standard paycheck knowing you did some good in the world. We can dream can't we?

Here is the main idea behind the singleton pattern. When we have something we want to create once and share (like a database connection object for instance), we should create an instance of it if it doesn't exist, otherwise return a reference to the object already in existence. Why create another copy of the exact same object and use more resources? I shall show you in an example. Below is a class called db. It controls access and establishes a connection to our database. Whenever we want to create a database connection it will either create it if it doesn't exist or give us the reference to the one connection in existence already.

PHP 5 Example

class db {
	// Static variable (available without needing an actual instance)
	private static $db_instance = null;
 
	private function __construct() {
		// Restrict the constructor, we don't want programmers to use it.
	}
 
	protected function __clone() {
		// We don't want them to clone either
	}
 
	// getInstance either creates an instance or returns our static variable version if it already exists.
	static public function getInstance() {
		if(is_null(self::$db_instance))
		{
			// Create database connection here
			$link = mysql_connect("localhost", "admin", "adminpass") or die(mysql_error());
			mysql_select_db("test_database",$link) or die(mysql_error()); 

			// Set our static variable to the link identifier. Now it is available in our static variable.
			self::$db_instance = $link;
		}
		return self::$db_instance;
	}
}



So the code above is pretty straight forward. I will show you this in action in just a moment. What we have done here is closed off the constructor and the clone implementations so that programmers will be forced to use our getInstance() method to create their object. The idea behind this method is that we test to see if we already have a link to our database, if not we create it and store it, otherwise we return the copy of the connection that is already made. Rather than having to create a database connection object each time and connect it, we can share one connection across the page, each time using getInstance() to either create the connection or give us the pointer to the current connection.

Here is an example of how we use it...

// fetch database connection (creates it if it wasn't created before)
$db_con = db::getInstance();

 
class DB_GetMember_Info {
 
	private $db = null;
	private $infoarray = array();
 
	public function __construct() {
		// Set our private member to existing connection
		$this->db = db::getInstance();

		// Now we use it to run our queries and pull up some members to store in our private array
		$result = mysql_query("select name, address, phone from members",$this->db);
		while ($member = mysql_fetch_object($result)) {
			array_push($infoarray,$member);
		}
	} 

	...
}



Notice how we access the getInstance() static method through the class name? We don't create the object, we simply access the static method using the name db. This is the same way you would access sqrt() through using the class name math in a language like C++ or Java.

Now the brilliant thing behind this is that we could create several copies of the DB_GetMember_Info class and one each one is created it is using the same connection link rather than creating and closing their own copies during creation.

The whole idea behind this pattern is saving resources by sharing something like a connection or maybe a whole "settings" object which sets and gets user settings. You would have one copy of the settings class created at any one time and multiple classes could use it without needing to create copies of the settings object. The one trick to remember about this pattern is that it uses a static variable. It must be static so that we can use the variable without needing to create instances of the object. This trick is also its primary drawback... it suffers from the same problem that global variables do because it is public and static very much a global environment. Thus it can be corruptible if you are not careful.

You will see this pattern in combination with other patterns since the pattern it provides is great for reducing redundant code and complexity, making other patterns easier as well. I hope this little glimpse into the singleton pattern will spur some new ideas of how you can go about developing better code and reducing the amount of work you have to do. Something like the connection idea above would be great for games or anything that may become connection intensive, constantly opening and closing the same connection.

Now go forth and speak the word of singleton to your co-workers, be leet, and show your boss that you kick ass because you belong to DIC!

If you want more blog entries like this, check out the official blog over on The Coders Lexicon. There you will find more code, more guides and more resources for programmers of all skill levels!

9 Comments On This Entry

Page 1 of 1

snoj 

29 September 2007 - 08:57 PM
A fast note, mysql_connect just returns an already open mysql link if they share the same connection information.
0

Martyr2 

30 September 2007 - 03:15 PM
Thanks for pointing out. Example app, nothing more.
0

skyhawk133 

02 October 2007 - 07:16 AM
Vote for this blog entry on DZone: http://www.dzone.com...ern_in_php.html
0

pentolino 

02 October 2007 - 08:12 AM
Sorry, what about concurrency and so on?
Say for example that an unwise programmer chooses to close that connection, what would the other users do?
Regards
0

snoj 

02 October 2007 - 11:28 AM
I think it would just re-open the connection.
0

pentolino 

02 October 2007 - 11:27 PM

hotsnoj, on 2 Oct, 2007 - 11:28 AM, said:

I think it would just re-open the connection.


Well I think I will close here; I see you don't care about concurrency here, that's it.
Don't get me wrong, probably it's ok for your tipical application, not for mine.
Regards
0

Martyr2 

03 October 2007 - 10:12 AM
hotsnoj is right. This would simply reopen the connection. The idea is simply that you either open the connection if it is not there otherwise it returns a reference.

Don't get bogged down too much in the idea of the connection being open or not. It was only an example of demonstrating the pattern. This pattern of course can be applied to many different situations. Another classic usage would be for something like settings object which would store system settings. You will want to create the settings on initial use by the client and then returned for every reference to the settings object. That way you wouldn't have various settings floating around for one use and potentially corrupting their session.

You will find this pattern particularly useful with something like the factory pattern where your settings would be an object which could carry a whole "basket" of other objects. You would create the factory object once and then return references to the same object on next reference to it.

Btw, don't dismiss the pattern just yet for your concurrency. This pattern is extremely useful for concurrency. Just not in our particular example.
0

pentolino 

07 October 2007 - 11:42 PM

Martyr2, on 3 Oct, 2007 - 10:12 AM, said:

hotsnoj is right. This would simply reopen the connection. The idea is simply that you either open the connection if it is not there otherwise it returns a reference.

Don't get bogged down too much in the idea of the connection being open or not. It was only an example of demonstrating the pattern. This pattern of course can be applied to many different situations. Another classic usage would be for something like settings object which would store system settings. You will want to create the settings on initial use by the client and then returned for every reference to the settings object. That way you wouldn't have various settings floating around for one use and potentially corrupting their session.

You will find this pattern particularly useful with something like the factory pattern where your settings would be an object which could carry a whole "basket" of other objects. You would create the factory object once and then return references to the same object on next reference to it.

Btw, don't dismiss the pattern just yet for your concurrency. This pattern is extremely useful for concurrency. Just not in our particular example.


Thanks for your reply; as you write the example is not the best possible fit and that was the point of my previous posts; it would have been better to use a different type of object (i.e.: one that has no state) to demonstrate the pattern.
I usually avoid the singleton pattern and let the user of the class decide wether or not to share an instance of that class between threads, unless the creation of an instance is really expensive.
As for the connection I usually use a connection pool.
Regards
0

Martyr2 

08 October 2007 - 12:52 AM
That is not entirely correct. The singleton pattern can applied despite the state and can be used effectively whether the object has state or not. If anything it would be more useful if the object had state, the idea is that you want to maintain an object in state than creating another that might be out of known state. You would create the object in a known state that you want to then share rather than setting up several instances that 1) Use unnecessary resources and 2) have to be juggled and 3) are virtually identical and have to maintain some sort of consistency and synchronization between all instances.

Now as far as your comment about threads and connection pools, I am not too sure how that is to apply to design style (which design patterns are). You are talking about implementation choice and again, if you wanted you could make a thread safe class which follows a singleton pattern. But you are right about implementing the singleton when class resources are high, that is the point of the design.

I think we have beaten down the idea that a connection object is not the best example, but it does provide a simple enough example to get the point across.

Thanks for the input! :)
0
Page 1 of 1

January 2022

S M T W T F S
      1
2345678
9101112131415
161718192021 22
23242526272829
3031     

Recent Entries

Recent Comments

Search My Blog

28 user(s) viewing

28 Guests
0 member(s)
0 anonymous member(s)