Singleton Pattern
Part of the Object Oriented Programming section of Coddy's PHP journey — lesson 71 of 91.
The Singleton Pattern is a creational design pattern that ensures a class has only one instance throughout your application's lifecycle. It also provides a global access point to that instance.
This pattern is useful when you need exactly one object to coordinate actions across the system, such as a database connection, configuration manager, or logger. Creating multiple instances of these would waste resources or cause inconsistent behavior.
Here's how to implement a Singleton in PHP:
<?php
class Database {
private static ?Database $instance = null;
private function __construct() {
// Private constructor prevents direct instantiation
}
public static function getInstance(): Database {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function query(string $sql): string {
return "Executing: $sql";
}
}
$db1 = Database::getInstance();
$db2 = Database::getInstance();
echo $db1 === $db2 ? "Same instance" : "Different instances";
Output:
Same instanceThe pattern relies on three key elements: a private constructor that prevents using new directly, a static property that holds the single instance, and a static method that creates the instance on first call and returns it on subsequent calls.
To make the Singleton truly bulletproof, you should also prevent cloning and unserialization:
<?php
private function __clone() {}
public function __wakeup() {
throw new Exception("Cannot unserialize singleton");
}
Challenge
EasyLet's build a configuration manager using the Singleton Pattern. In real applications, you typically want a single source of truth for configuration settings — having multiple configuration objects could lead to inconsistent behavior across your system.
You'll organize your code across two files:
Config.php— Create aConfigclass that implements the Singleton Pattern. Your configuration manager should:- Store settings in a private array property
- Have a private constructor that initializes the settings array as empty
- Provide a static
getInstance()method that returns the single instance - Prevent cloning by making
__clone()private - Include a
set(string $key, string $value): voidmethod to store a setting - Include a
get(string $key): ?stringmethod that returns the value for a key, ornullif the key doesn't exist - Include a
getAll(): arraymethod that returns all settings
main.php— Include the Config file. You'll receive two inputs: a key and a value.Get the Config instance and set a default setting with key
"app_name"and value"MyApp".Get a second reference to the Config instance (using
getInstance()again) and use it to set another setting using the key and value from the inputs.Finally, verify the Singleton is working correctly:
- Print
"Same instance: true"or"Same instance: false"based on whether both references point to the same object (use===to compare) - Print
"Settings count: [count]"showing the total number of settings stored (usecount()on the result ofgetAll()) - Print
"App name: [value]"showing the app_name setting retrieved through the second reference
- Print
This challenge demonstrates the core benefit of the Singleton Pattern: no matter how many times you call getInstance(), you always get the same object, ensuring all parts of your application share the same configuration state.
Cheat sheet
The Singleton Pattern ensures a class has only one instance throughout your application's lifecycle and provides a global access point to that instance.
This pattern is useful for objects like database connections, configuration managers, or loggers where multiple instances would waste resources or cause inconsistent behavior.
Basic Singleton implementation:
<?php
class Database {
private static ?Database $instance = null;
private function __construct() {
// Private constructor prevents direct instantiation
}
public static function getInstance(): Database {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
}
$db1 = Database::getInstance();
$db2 = Database::getInstance();
echo $db1 === $db2 ? "Same instance" : "Different instances";
// Output: Same instance
Key elements:
- Private constructor — prevents using
newdirectly - Static property — holds the single instance
- Static method — creates the instance on first call and returns it on subsequent calls
Preventing cloning and unserialization:
<?php
private function __clone() {}
public function __wakeup() {
throw new Exception("Cannot unserialize singleton");
}
Try it yourself
<?php
require_once 'Config.php';
// Read input
$key = trim(fgets(STDIN));
$value = trim(fgets(STDIN));
// TODO: Get the Config instance and set "app_name" to "MyApp"
// TODO: Get a second reference to Config using getInstance() again
// TODO: Use the second reference to set the setting using $key and $value from input
// TODO: Verify Singleton is working:
// - Print "Same instance: true" or "Same instance: false" based on === comparison
// - Print "Settings count: [count]" showing total settings
// - Print "App name: [value]" showing app_name retrieved through second reference
?>This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe $this KeywordMethodsPropertiesConstructor (__construct)Destructor (__destruct)Recap - Simple Calculator4Inheritance
Basic InheritanceThe parent:: KeywordMethod OverridingThe final KeywordAbstract ClassesRecap - Employee Hierarchy7Encapsulation
Public, Protected, PrivateAccess Modifiers in DepthGetters and SettersInformation HidingConstructor Promotion (8.0)Recap - Student Records System2Namespaces & Autoloading
Introduction to NamespacesThe use KeywordPSR-4 Autoloading StandardComposer AutoloaderRecap - Organized Project5Interfaces & Contracts
Introduction to InterfacesImplementing InterfacesMultiple Interface ImplementInterface vs Abstract ClassType Hinting with InterfacesRecap - Shape Calculator8Magic Methods
Magic Methods Introduction__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Object Cloning__serialize & __unserializeRecap - Custom Collection11Type System & Error Handling
Type DeclarationsNullable TypesUnion & Intersection TypesException ClassesCustom Exception HierarchyTry, Catch, FinallyRecap - Form Validator14Project: Library Management
Project OverviewBook and User Classes3Class Properties
Instance vs Static PropertiesConstants in ClassesStatic Methods & PropertiesPrivate & Protected PropertiesReadonly Properties (PHP 8.1)Recap - Bank Account Manager6Polymorphism
Method Overriding RevisitedPolymorphism via InterfacesType Hinting & Union TypesLate Static BindingRecap - Payment Processor9Traits
Introduction to TraitsUsing Multiple TraitsTrait Conflict ResolutionAbstract Methods in TraitsTraits vs Inheritance12Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy Pattern