Programming Languages
PHP
Subjective
Sep 23, 2025
Implement a thread-safe singleton pattern in PHP using modern techniques. Discuss the challenges and alternatives.
Detailed Explanation
Thread-Safe Singleton Implementation:
final class DatabaseConnection {
private static ?self $instance = null;
private static object $lock;
private PDO $connection;
private function __construct() {
// Initialize lock object for thread safety
if (!isset(self::$lock)) {
self::$lock = new stdClass();
}
$this->connection = new PDO(
"mysql:host=localhost;dbname=app",
"user", "password",
[PDO::ATTR_PERSISTENT => true]
);
}
public static function getInstance(): self {
if (self::$instance === null) {
// Double-checked locking pattern
synchronized(self::$lock, function() {
if (self::$instance === null) {
self::$instance = new self();
}
});
}
return self::$instance;
}
public function getConnection(): PDO {
return $this->connection;
}
// Prevent cloning and unserialization
private function __clone() {}
private function __wakeup() {}
public function __serialize(): array {
throw new Exception("Singleton cannot be serialized");
}
}
Modern Alternative - Dependency Injection:
// Service Container Approach
class Container {
private array $services = [];
private array $singletons = [];
public function singleton(string $abstract, callable $factory): void {
$this->services[$abstract] = $factory;
$this->singletons[$abstract] = true;
}
public function get(string $abstract): mixed {
if (isset($this->singletons[$abstract])) {
static $instances = [];
return $instances[$abstract] ??= $this->services[$abstract]();
}
return $this->services[$abstract]();
}
}
// Usage
$container = new Container();
$container->singleton(DatabaseConnection::class, fn() => new DatabaseConnection());
// Thread-safe through container
$db = $container->get(DatabaseConnection::class);
Challenges with Singleton:
- Testing: Difficult to mock and test
- Thread Safety: Requires synchronization in multi-threaded environments
- Global State: Creates hidden dependencies
- Scalability: Can become bottleneck in high-concurrency applications
Better Alternatives:
- Dependency Injection: More testable and flexible
- Service Locator: Centralized service management
- Factory Pattern: Better control over object creation
- Connection Pooling: For database connections specifically
Discussion (0)
No comments yet. Be the first to share your thoughts!
Share Your Thoughts