Singleton is a design pattern that restricts the instantiation of the class, usually to one object. It is useful when you need one instance throughout whole project, it may be used for Caching, Logging, Database and etc.

For this example we’ll be doing just that - we’ll create a Logger class that allows for exactly one object.

It is worth noting that there are two types of Singleton initialization: Lazy (initializes only when required) and Eager (initializes always). We’ll use only lazy initialization for this example.

Logger class

By default Singleton pattern requires a getInstance() method. We also need to add logs (log($message) method) and to get all logs (get_logs() method). For storage we’ll use a simple array.

So far we’ll need these methods:

  • getInstance()
  • log($message)
  • get_logs()

So let’s go.

First, let’s define our base class with method definitions:

<?php

/**
 * Logger class
 * Singleton using lazy implementation
 */
class Logger
{
    private static $instance = NULL;
    private $logs;

    private function __construct() {}
    public function getInstance() {}
    public function log($message) {}
    public function get_logs() {}
};

Note that we made our __construct() method private. That is a part of the Singleton design pattern and that’s how we will be limiting instantiation of our Logger class.

Next, let’s define __construct() method to set $logs to array():

<?php
private function __construct() {
    $this->logs = array();
}

Then we need to define getInstance() class. It needs to return $instance and instantiate itself if necessary.

<?php
public function getInstance() {
    // Instantiate itself if not instantiated
    if(self::$instance === NULL) {
        self::$instance = new Logger();
    }
    return self::$instance;
}

We’re almost there. Now let’s define our logging methods:

<?php
public function log($message) {
    if(!empty($message)) {
        $this->logs[] = $message;
    }
}

public function get_logs() {
    return $this->logs;
}

The completed class:

<?php

/**
 * Logger class
 * Singleton using lazy implementation
 */
class Logger
{
    private static $instance = NULL;
    private $logs;

    private function __construct() {
        $this->logs = array();
    }

    public function getInstance() {
        // Instantiate itself if not instantiated
        if(self::$instance === NULL) {
            self::$instance = new Logger();
        }
        return self::$instance;
    }

    public function log($message) {
        if(!empty($message)) {
            $this->logs[] = $message;
        }
    }

    public function get_logs() {
        return $this->logs;
    }
};

And lastly let’s create main.php that will test out our Logger class.

<?php
require 'Logger.php';

$logger = Logger::getInstance();
$logger->log('This is my first logged message!');
print_r($logger->get_logs()); // Print out all logs

// Let's use method chaining
Logger::getInstance()->log('This is my second logged message!');
print_r($Logger::getInstance()->get_logs());

Now if you’d run main.php using php main.php command, you should get this output:

Array
(
    [0] => This is my first logged message!
)
Array
(
    [0] => This is my first logged message!
    [1] => This is my second logged message!
)

If you do, you’re done! You’ve successfully implemented the Singleton pattern!

I’ve created a pattern repository on GitHub where you can find this and other design patterns already implemented.