The Singleton Design Pattern in PHP is a creational pattern that ensures:
- Only one instance of a class exists during the lifetime of the application.
- 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
Database::getInstance()checks if an instance already exists.- If not, it creates one and stores it in
self::$instance. - All calls to
getInstance()return the same object. private __clone()andprivate __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)
