PHP Singleton Pattern: How to Use with Examples

php singleton pattern

The PHP singleton design pattern makes sure that the class has only one instance and provides a global access point to that instance.

You will cover how the Singleton design pattern works in PHP with examples in this article. Let’s get started.

Understand the PHP Singleton Design Pattern

The PHP singleton design pattern restricts object creation to a single instance and prevents the creation of multiple objects.

  • Use it if you need a single or shared resource like a database connection or logging system.
  • Ideal for classes that manage global state or configuration settings.
  • It makes sure that the resource is centralized and accessible throughout your application.

Here is a basic example:

class SingletonExample {
     
    private static $instance = null;
    private function __construct() {}
    private function __clone() {}

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

Here is how to use it:

$singleton1 = SingletonExample::getCBInstance();
$singleton2 = SingletonExample::getCBInstance();

 
var_dump($singleton1 === $singleton2); 

The output:

bool(true)

Here is how it works:

The SingletonExample class makes sure only one instance is created by a private static variable.

It also prevents direct instantiation and cloning. The getCBInstance() method checks if the instance exists, creates one if it is not found, and returns it.

Let’s move on to the section below to understand the difference between a singleton and a static class in PHP.

Singleton vs. Static Class in PHP

Singleton:

The singleton pattern ensures that a class creates only one instance. It supports lazy initialization, so the system generates the instance only when necessary.

This pattern manages state and enables dependency injection or class extension.

Static Class:

A static class doesn’t require an instance. It uses static methods and properties that can be accessed directly.

It does not have the concept of a single instance and cannot be extended or have its state managed in the same way as a Singleton.

Lazy vs. Eager Initialization in Singleton

Lazy Initialization:

  • It creates the instance only when it is first needed.
  • This can save resources if the singleton instance is not used in the application’s lifecycle.
  • It is generally preferred when there’s a possibility that the instance may never be used.

Here is an example:

final class ApplicationRegistry
{
    private static ?self $singletonInstance = null;

    // Prevent instantiation and cloning
    private function __construct() {}
    private function __clone() {}
    public function __wakeup(): void
    {
        throw new \RuntimeException("Cannot unserialize singleton");
    }

    // Thread-safe(ish) instance retrieval
    public static function getShared(): self
    {
        if (self::$singletonInstance === null) {
            self::$singletonInstance = new self();
        }
        
        return self::$singletonInstance;
    }

    
    public function getConfig(): array
    {
        return ['env' => 'production', 'debug' => false];
    }
}

// Here is how to use it
$app = ApplicationRegistry::getShared();
$config = $app->getConfig();
print_r($config);

The output:

Array
(
[env] => production
[debug] =>
)

In this code, we make sure we can create only one object from it. The constructor is private, so you can’t use new outside the class. The getShared() method gives you a single instance.

It creates an instance if it does not exist, and it returns the same one if it already exists.

Eager Initialization:

  • It creates the instance as soon as the class is loaded.
  • This way is useful when you know the instance will always be needed, and you want to avoid the overhead of checking and creating it later.

For example:

class SingletonExample {
    private static $instance = new Singleton();

    private function __construct() {}

    private function __clone() {}

    public static function getCBInstance() {
        return self::$instance;
    }
}

How to Prevent Cloning and Unserialization in Singleton

You can use the following techniques to do that:

  • Use a private __clone() method to prevent other code from cloning the Singleton instance using clone.
  • Use a private __wakeup() method is automatically called when the instance is unserialized. That is when you give it private, you prevent the instance from being unserialized.

Here is an example:

class clap{ 

    private static $instance = null;
 
    private function __construct() {}
 
    private function __clone() {}
 
    private function __wakeup() {}
 
    public static function getClap() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
}
  • Private __clone() method prevents cloning by making it private.
  • Private __wakeup() method prevents unserialization by making it private.

Here is an example of how to use them:

$instance1 = clap::getClap();
$instance2 = clap::getClap();

 
var_dump($instance1 === $instance2);  

 
$clone = clone $instance1;  


// => Warning 
$serialized = serialize($instance1);

// => Fatal Error
$unserialized = unserialize($serialized);  

The output:

bool(true)

PHP Warning: The magic method clap::__wakeup() must have public visibility in /HelloWorld.php on line 11

PHP Fatal error: Uncaught Error: Call to private clap::__clone() from global scope in /HelloWorld.php:29
Stack trace:

You ensure that the Singleton instance cannot be cloned or unserialized when you use this. It maintains the integrity of the pattern.

PHP Singleton for Database Connection

The singleton design pattern for a database connection in PHP ensures that only one instance of the database connection is created. It saves resources and improves performance.

Here’s how to implement it:

namespace MyApp;

class DatabaseConnection {
    
    private static $instance = null;
    
    
    private $connection;

   
    private function __construct() {
        
        $host = 'localhost';
        $dbname = 'your_database';
        $username = 'your_username';
        $password = 'your_password';
        
        
        try {
            $this->connection = new \PDO("mysql:host=$host;dbname=$dbname", $username, $password);
            $this->connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
        } catch (\PDOException $e) {
            die("Connection failed: " . $e->getMessage());
        }
    }

    
    private function __clone() {}

    
    private function __wakeup() {}

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

    
    public function getConnection() {
        return $this->connection;
    }
}

Here is how to use this class:

namespace MyApp\Utilities;

use MyApp\DatabaseConnection;


$db1 = DatabaseConnection::getCBInstance();
$db2 = DatabaseConnection::getCBInstance();


var_dump($db1 === $db2); 


$connection = $db1->getConnection();


$query = $connection->query('SELECT * FROM users');
$results = $query->fetchAll(\PDO::FETCH_ASSOC);
var_dump($results);
  1. The variable holds the single instance of the DatabaseConnection class.
  2. The constructor initializes the database connection using PDO. It’s private to prevent direct instantiation.
  3. Private __clone() and __wakeup() methods prevent cloning and unserialization of the DatabaseConnection instance.
  4. The getCBInstance() method checks if the $instance is already created. If not, it creates the instance and returns it.
  5. getConnection() method returns the actual PDO database connection. That allows you to interact with the database.

Wrapping Up

In this article, you learned that the Singleton design pattern ensures that a class has only one instance. It provides a global access point to that instance.

Here is a quick recap:

  • The Singleton pattern restricts object creation to a single instance and prevents cloning or unserialization of the instance.
  • You explored how it differs from a static class. It offers benefits like lazy initialization and the ability to manage state.
  • You also learned about the use of namespaces to organize Singleton classes and how to apply it to manage a database connection.

Previous Article

PHP Filters: How to Validate and Sanitize User Inputs

Next Article

PHP error_log Function: How It Works with Examples

Write a Comment

Leave a Comment

Your email address will not be published. Required fields are marked *

Subscribe to Get Updates

Get the latest updates on Coding, Database, and Algorithms straight to your inbox.
No spam. Unsubscribe anytime.