Home / Singletons: Implementing Singletons in PHP

Singletons: Implementing Singletons in PHP

Singletons are one of many design patterns that developers employ to solve common problems. In this three-part series, we will look at what they are, when to use them, some different types of singletons, and how to implement them yourself.

This post is at an intermediate level as it contains complete code snippets involving Object Oriented concepts. Although this post has examples in PHP, the concepts it describes apply to all object-oriented programming languages.

New to this series?

If this is the first post in this series you are reading, I recommend jumping back and having a look at: Singletons: What are they and When to use them, and Singletons: Two ways about it.

In this post, we will be implementing two types of global data containers, an object singleton, and a static class. Our object singleton will be called ‘SingletonRequestData’ and our static class ‘StaticRequestData’, but they will both do exactly the same thing.

For the examples, these data structures will provide us with the connection time, connection age, and requester’s I.P address. The published final code contains additional fields to demonstrate a more fleshed out class.

A sprinkling of keywords

If you are unfamiliar with Object Oriented programming in PHP, let’s first have a look at some of the keywords you will see in the coming examples.

// the class keyword declares a class. Classes are essentially collections of functions and variables.
class MyClass {

// private variables and functions are only accessible inside the class itself
private $age;
private GetAge() {
// $this refers to the current instance of the class we are in.
return $this->age
}

// public variables and functions are available to all other code
public $name;
public GetName() {
return $this->name;
}

// Static variables are only available through the class name
public static $size;
// For example, this function would be called using MyClass::GetSize()
public static GetSize() {
// self refers to the current class name, in this context, it would be ‘MyClass’
return self::$size;
}
}

With that aside, let’s get to building some singletons!

Getting setup

These are the core singleton bits. This can be considered the boilerplate for the singletons.

Object Singleton

class SingletonRequestData {

private static $instance;

private function __construct() {
}

public static function GetInstance() {
if ( self::$instance ) {
return self::$instance;
}
self::$instance = new SingletonRequestData();
}
}

We are creating a variable to store our singleton called $instance, and providing a method ‘GetInstance’ to access it.

The private __construct method means that no other piece of code is permitted to create a new SingletonRequestData instance. This is what makes our singleton a singleton; no one else can create another one!

The GetInstance method first checks to see if an instance exists, creating a new instance if not. This, together with the private __construct method, ensures that there can never be more than one of this class.

Static Class

class StaticRequestData {

private function __construct() {
}
}

In the static class variation, we still want a private __construct method, as we still want to prevent instantiation of our class. However, since we aren’t calling it ourselves, there will be exactly zero instances of this class, forever.

At this point it may seem like the static class is significantly simpler, however, the next section balances the two out.

Adding some data

Next, let’s add some variables to store or data, and some logic to initialise these to our desired values.

In each of the code examples, I will be excluding code from the previous examples. The full code can be found here: Singleton Demo code on GitHub.

Object Singleton

class SingletonRequestData {

private $requester_ip;
private $connection_time;

private function __construct() {
$this->requester_ip = $_SERVER[‘REMOTE_ADDR’];
$this->connection_time = time();
}

}

First off, we are declaring two private variables, ready to store our global data.

Next, we are adding to the private __construct method from the last part, to initialise these variables to useful values.

Static Class

class StaticRequestData {

private static $initialized = false;

private static $requester_ip;
private static $connection_time;

public static function __init() {

if ( self::$initialized ) {
return;
}
self::$initialized = true;

self::$requester_ip = $_SERVER[‘REMOTE_ADDR’];
self::$connection_time = time();
}
}

StaticRequestData::__init();

For the static class, we have an additional variable $initialized. This variable will track whether the class has been setup yet or not, with the aim to prevent the class being setup twice.

Next, its the same two variables as in the object singleton, however, this time they are both static.

Here, we can’t use the __constructor to set up our static class, as mentioned, it will never be called. Instead, we add an __init function. This function first ensures that it has never been called before, by checking the $initialized variable. Then it initialises variables as before.

Finally, on line 20, you will see a static call to the __init method, outside the class. This ensures that if this file is included in a project, and the static class declared, it is always initialzed.

Give that data out

Finally we need to add accessor functions for our data.

Object Singleton

class SingletonRequestData {

public function GetRequesterIP() {
return $this->requester_ip;
}

public function GetConnectionUnixTime() {
return $this->connection_time;
}

public function GetConnectionAge() {
return time() – $this->connection_time;
}

}

This code is pretty standard PHP. Since we have already done all the work making this class a singleton, our accessor function can just act like any other object function.

Static Class

class StaticRequestData {

public static function GetRequesterIP() {
return self::$requester_ip;
}

public static function GetConnectionUnixTime() {
return self::$connection_time;
}

public static function GetConnectionAge() {
return time() – self::$connection_time;
}
}

There isn’t much special going on here either.

The functions are all declared as static, as with everything else in a static class.

Then, instead of using ‘$this->’, we use ‘self::’. Watch out however, there is a pesky $! when using ‘self::’, we need a $ before the variable name. The below example shows this:

// In a singleton:
$this->requester_ip;
// In a static class:
self::$requester_ip;

Using our shiny new Data structures

<?php
require_once ‘object-singleton.php’;
require_once ‘static-singleton.php’;

// This is so our connection age doesn’t always show 0
sleep( 1 );
?>
<!DOCTYPE html>
<html>
<head>
<title> Singletons Demo </title>
</head>
<body>
<h1> Requester Info </h1>
<table>
<thead>
<tr>
<th>Data</th>
<th>Singleton Value</th>
<th>Static Class Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>IP:</td>
<td><?php echo SingletonRequestData::GetInstance()->GetRequesterIP(); ?></td>
<td><?php echo StaticRequestData::GetRequesterIP(); ?></td>
</tr>
<tr>
<td>Connection Unix Time</td>
<td><?php echo SingletonRequestData::GetInstance()->GetConnectionUnixTime(); ?></td>
<td><?php echo StaticRequestData::GetConnectionUnixTime(); ?></td>
</tr>
<tr>
<td>Connection Age</td>
<td><?php echo SingletonRequestData::GetInstance()->GetConnectionAge(); ?></td>
<td><?php echo StaticRequestData::GetConnectionAge(); ?></td>
</tr>
</tbody>
</table>

</body>
</html>

There is a bit of HTML boilerplate to look through here. However, starting on line 25 we can see our classes in use.

The above code renders the following page:

Rendered page

All together now

The complete project can be found here: Singleton Demo code on GitHub.

Hopefully, by now, you know all about Singletons, what they are for, how to use them, and a couple of different options for implementing them. However, if you still have questions, feel free to comment below.