Design Pattern: Singleton Pattern in PHP

Singleton pattern is used to ensure that only an instance of a class is created. Each time an attempt to create an instance of the class will return the same instance.

Implementation of the Singleton pattern in PHP follows the same steps as Java and TypeScript.

Implementation

Follow the steps below for Singleton pattern implementation in PHP-

  • Create Singleton class. We need to make sure that an instance of this can not be created outside of the class.
  • Define the construction of the class as private, so that an instance can not be created directly using the “new” keyword.
  • Define a class property as of the type of the same class, this property will hold an instance of the Singleton class.
  • Create a method for generating instance. If an instance already exists then return that, if the instance does not exist then create new instance, then create a new instance and return that.

Here is a simple example of Singleton pattern implementation in PHP-

<?php
// Singleton pattern implementation in PHP

class Singleton {
    // Make sure to make the "private" and "static"
    private static ?Singleton $singletonInstance = null;

    // Make sure to make the constructor "private"
    private function __construct(private string $someVal) {}

    // Make sure to make the function "static"
    public static function getInstance(string $someVal): Singleton {
        // Check if an instance already exists
        if (!self::$singletonInstance) {
            // If instance does not exist then create an instance
            // and assign that to "singletonInstance"
            self::$singletonInstance = new Singleton($someVal);
        }

        // Return the "singletonInstance"
        return self::$singletonInstance;
    }

    public function printDetails() {
        echo "\nsome val: " . $this->someVal;
    }
}

// Demo

// Use the singleton implementatin like below
$mySingletonInstance = Singleton::getInstance("abc");
$mySingletonInstance->printDetails();


// Try using another instance
$anotherInstance = Singleton::getInstance("changed val");
$anotherInstance->printDetails();

// New instance can not be created using the "new" keyword
// as the constructor is declared as "private".
// An attempt like below will generate error
// const someSingletonInstance = new Singleton(); 

Following output will be generated-

some val: abc
some val: abc

Examples

Here are a few examples of PHP-

Example #1: Database Connection

For this example, let’s consider the creation and management of a database connection.

Here we are using Singleton pattern, so that the same instance is returned always, and the same connection can be always used.

DB Connection Singleton Class

  • Create file “DbConnSingleton.php”.
  • Create class “DbConnSingleton”.
  • Define property named “singletonInstance” of type of the same class “DbConnSingleton” and set it to null.
  • Define constructor as private. Accept values for “host”, “port”, “username” and “password” and set that to class property of the same name.
  • Create method “getInstance” which accepts param to create an instance. Check if the value of “$singletonInstance” if already set or not. If already set then return that. If instance is not set, then create a new instance and then return that.
  • Define utility methods “printConnectionDetails” to print connection details.
<?php
// DbConnSingleton.php

namespace BigBoxCode\DesignPattern\Singleton\DbConnection;

class DbConnSingleton {
    private static ?DbConnSingleton $singletonInstance = null;

    private function __construct(
        private string $host,
        private int $port,
        private string $username,
        private string $password
    ) {
    }

    public static function getInstance(string $host, int $port, string $username, string $password): DbConnSingleton {
        if (self::$singletonInstance) {
            echo "\nUsing existing db connection instance";
            return self::$singletonInstance;
        }

        echo "\nCreating new db connection instance";
        self::$singletonInstance = new DbConnSingleton($host, $port, $username, $password);

        return self::$singletonInstance;
    }

    public function printConnectionDetails() {
        echo "\nhost:" . $this->host;
        echo "\nport:" . $this->port;
        echo "\nusername:" . $this->username;
        echo "\npassword:" . $this->password;
    }

    public function executeQuery($query) {
        echo "\nExecuting query: " . $query;
    }
}

Demo

Create an instance of the “DbConnSingleton”, by sending some value of host, port, username, and password to the method “getInstance”.

Then if we try to create another instance of “DbConnSingleton” instance by calling the “getInstance” method.

If we check the connection details then we fined that, it has the same connection as the previous one.

<?php
// demo.php

require __DIR__ . '/../../vendor/autoload.php';

use BigBoxCode\DesignPattern\Singleton\DbConnection\DbConnSingleton;

// Create database instance
$dbConnOne = DbConnSingleton::getInstance('loclahost', 1234, 'root', 'secret!pass');

echo "\nDB connection details for dbConnOne:";
$dbConnOne->printConnectionDetails();

// Try to create another database instance
$dbConnTwo = DbConnSingleton::getInstance('192.168.55.55', 2222, 'root2', 'secret!pass2');

echo "\nDB connection details for dbConnTwo:";
$dbConnTwo->printConnectionDetails();

Output

Following output is generated by the above code-

Creating new db connection instance

DB connection details for dbConnOne:
host:loclahost
port:1234
username:root
password:secret!pass


Using existing db connection instance

DB connection details for dbConnTwo:
host:loclahost
port:1234
username:root
password:secret!pass

Example #2: Setting

Let’s check another example of the setting or configuration values of the application.

Setting Singleton Class

  • Create file “Setting.php”.
  • Create class “Setting”.
  • Define property named “settingInstance” of type “Setting”.
  • Define an array “props” to store setting properties.
  • Make the constructor as private.
  • Create method “getInstance”. Check if the value of “$settingInstance” already exists or not. If not set, then create a new instance. Then finally return the instance.
  • Define methods for getting and setting the properties.
<?php
// setting.php

namespace BigBoxCode\DesignPattern\Singleton\Setting;

class Setting {
    private static ?Setting $settingInstance = null;
    private $props = [];

    // Make sure to define a private constructor
    private function __construct() {
    }

    public static function getInstance(): Setting {
        if (empty(self::$settingInstance)) {
            self::$settingInstance = new Setting();
        }

        return self::$settingInstance;
    }

    public function set(string $key, mixed $value): void {
        $this->props[$key] = $value;
    }

    public function get(string $key): mixed {
        if (isset($this->props[$key])) {
            return $this->props[$key];
        }

        return null;
    }

    public function getAll() {
        return $this->props;
    }
}

Demo

Use the method “getInstance” to create a new instance of the setting class.

<?php
// demo.php

require __DIR__ . '/../../vendor/autoload.php';

use BigBoxCode\DesignPattern\Singleton\Setting\Setting;

// Create setting instance
$setting = Setting::getInstance();

$setting->set("file_base_path", "/var/log/dd");
$setting->set("app_port", 3000);

var_dump($setting->getAll());

// Try to create another instance
$setting2 = Setting::getInstance();

var_dump($setting2->getAll());

Output

array(2) {
  ["file_base_path"]=>
  string(11) "/var/log/dd"
  ["app_port"]=>
  int(3000)
}

array(2) {
  ["file_base_path"]=>
  string(11) "/var/log/dd"
  ["app_port"]=>
  int(3000)
}

Source Code

Use the following link to get the source code:

Other Code Implementations

Use the following links to check Singleton pattern implementation in other programming languages.

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.

Uncover the professional journey shaping your projects. Explore my profile on the About page.