Explain the Singleton design pattern in PHP.

Singleton design pattern

The Singleton Design Pattern in PHP is a creational pattern that ensures:

  1. Only one instance of a class exists during the lifetime of the application.
  2. That instance is globally accessible.

This is useful when you want a single point of access to a resourceβ€”like a database connection, logger, or configuration manager.


Key Concepts

  • Private constructor β†’ Prevents creating new objects from outside.
  • Static property β†’ Stores the single instance.
  • Public static method β†’ Provides global access to the instance.
  • Private clone method β†’ Prevents cloning of the instance.
  • Private wakeup method β†’ Prevents unserialization.

Example: Singleton for Database Connection

<?php
class Database {
    private static $instance = null; // Holds the single instance
    private $connection;

    // Private constructor so no one can instantiate directly
    private function __construct() {
        $this->connection = new mysqli("localhost", "root", "", "test_db");
        if ($this->connection->connect_error) {
            die("Database connection failed: " . $this->connection->connect_error);
        }
    }

    // Prevent cloning
    private function __clone() {}

    // Prevent unserializing
    private function __wakeup() {}

    // Access method to get the single instance
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    // Method to get the connection
    public function getConnection() {
        return $this->connection;
    }
}

// Usage
$db1 = Database::getInstance();
$db2 = Database::getInstance();

if ($db1 === $db2) {
    echo "Same instance of database connection";
}
?>

How it works

  1. Database::getInstance() checks if an instance already exists.
  2. If not, it creates one and stores it in self::$instance.
  3. All calls to getInstance() return the same object.
  4. private __clone() and private __wakeup() ensure no copies are made.

Advantages

βœ… Saves memory and resources (only one object is created).
βœ… Centralized control over the instance.
βœ… Good for managing shared resources like configuration or logging.

Disadvantages

❌ Can introduce global state (harder to test in unit tests).
❌ Overused in wrong contexts can lead to tight coupling.

Let’s take a real-world PHP example of the Singleton design pattern:

We’ll use a Logger class that writes logs to a file.
In many applications, you want a single logging instance so all parts of the app write to the same file without creating multiple file handlers.


Real-World Example: Logger

<?php
class Logger {
    private static $instance = null;
    private $fileHandle;

    // Private constructor to prevent direct creation
    private function __construct() {
        $logFile = __DIR__ . "/app.log";
        $this->fileHandle = fopen($logFile, "a");
        if (!$this->fileHandle) {
            throw new Exception("Could not open log file.");
        }
    }

    // Prevent cloning
    private function __clone() {}

    // Prevent unserializing
    private function __wakeup() {}

    // Get the single instance
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    // Write message to log file
    public function log($message) {
        $time = date("Y-m-d H:i:s");
        fwrite($this->fileHandle, "[$time] $message" . PHP_EOL);
    }

    // Close file handle on object destruction
    public function __destruct() {
        fclose($this->fileHandle);
    }
}

// Usage Example:
$logger1 = Logger::getInstance();
$logger1->log("User logged in.");

$logger2 = Logger::getInstance();
$logger2->log("User updated profile.");

// Both $logger1 and $logger2 are the same instance
if ($logger1 === $logger2) {
    echo "Only one logger instance is being used.";
}
?>

Where you can use this in PHP projects

  • Database Connection Manager (most common)
  • Logging System (like above)
  • Configuration Loader (load config once, use everywhere)
  • Caching Manager (e.g., Redis or Memcached handler)
  • Session Manager (centralized session handling)
No comments yet! You be the first to comment.

Leave a Reply

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