Menu
Coddy logo textTech

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 instance

The 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 icon

Challenge

Easy

Let'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 a Config class 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): void method to store a setting
    • Include a get(string $key): ?string method that returns the value for a key, or null if the key doesn't exist
    • Include a getAll(): array method 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 (use count() on the result of getAll())
    • Print "App name: [value]" showing the app_name setting retrieved through the second reference

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 new directly
  • 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

?>
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming