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.
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