How to use the Singleton Pattern with PHP Examples in 2023

What is the Singleton Pattern in PHP

Singleton pattern in PHP is easy to implement as we will see a Database class that ensures that there’s only one Database instance available application-wide. That’s what Singleton is all about.

Singleton Pattern in PHP
Singleton Pattern in PHP

Just one class and that’s Singleton for you. Does it sound too naive compared to other patterns? Rightly guessed. But it is worth knowing Singleton and its ups and downs. So, stay tuned to learn more about the one and only Singleton.

Definition | Singleton Design Pattern in PHP

Singleton is a creational design pattern that ensures that only one instance of an object exists and is accessible globally.

Singleton Pattern in PHP
Singleton Pattern

The objective of the pattern is to have more control over a global object. It makes sure to have one, and only one instance of an object and that object is accessible globally.

Database Object | A Real World Example of Singleton Pattern in PHP

Let’s say you have a basic CRUD application with several data models. These data models represent entities in your database, and each model has distinct methods for doing CRUD. The baseline is that these models use a database instance to communicate with the database.

Now, if all these models have a separate database instance, that would choke the application memory because the database object tends to be a heavy-weight resource. So, we need to ensure that.

  • One and only one database object exists.
  • This database object is accessible globally application-wide. 

So, how to go about it?

A Global Variable…Right?

So, most of us think of a global variable. A global variable has application-wide access. But does it guarantee that only one instance of an object exists at a time? Definitely not! Your application can instantiate a new object and pass it on to the global variable.

But perhaps you think, what if we make a global variable constant? Then the application can’t overwrite it. Yes, but that’s not the only thing that matters. There are some other concerns linked to using a global variable.

Eager loading vs Lazy loading

What are eager and lazy loading? Let’s understand eager loading by understanding lazy loading. Lazy loading is an optimization technique where heavy resources or computations are put off until the application actually needs it. 

Think of it this way. An application could have a driver connect and talk to your printer. Is it good to load the driver as soon as your application starts? Your application may be busy doing some other stuff at startup so why bother loading the driver up in the memory and hamper other processes?

You can load it when you hit that print button in your application, which is what lazy loading is. Now, eager loading is just the opposite of it.

So, one limitation of the global variable is that the application loads it into memory right away. It can’t defer it. Though there are some workarounds, global variables alone can’t do that. 

Confusion in the namespace

Namespaces and scopes are always mind-boggling aspects of programming. You have global and local scopes. Local scopes can declare variables that can shadow the global ones. Also, programmers are likely to declare variables with conflicting names unintentionally. These are more often done in large codebases.

So, we should ensure that global data is encapsulated in one space. That’s one way to avoid such conflicts in your application. Such an encapsulated space is preferable from a design POV.

Introducing Singleton

So, Singleton is the hero here, or we could say the only hero because there are no more than one singleton in an application. Singleton class guarantees the two properties or requirements that we need.

  • It ensures that an object is accessible globally.
  • It also ensures that only one instance of the object exists.

That’s clear, but how do we go about it? How to make a Singleton class? Let’s see that up next.

Singleton Class

Singleton class ain’t rocket science. You need to understand a couple of OOP constructs – private constructors and static methods. If you are not sure about this, don’t worry because you will be able to understand that when they are put to use.

Singleton Class with Private Constructor
Singleton Class with Private Constructor

Having a private constructor means that only the Singleton class can instantiate an object using the new keyword, and anything outside can’t do so.

Hmmm…? What’s the benefit if the constructor is private? We can’t instantiate objects of this class using the new keyword. 

Well, that’s right? Now let’s add a method that will make Singleton what it is meant to be.

Singleton Class with Static Members
Singleton Class with Static Members

See the keyword static? A static member belongs to a class and is shared amongst the objects. This means that you are not bound to create objects of the class to access its static members. You can call the static method in the class. 

Calling the static getInstance()
Calling the static getInstance()

Debunking the static function

Well, the function is easy to read. Just a note about the static variable uniqueInstance. It is static because we need to access it in the static function getInstance(). That’s because static functions should access static members only. 

That’s what OOP says, and that makes sense because static members are shared contrary to the non-static data distinct to an object.

So, calling the static function does the following.

  • Checks if uniqueInstance exists. If false, initialise it with a new Singleton object.
if($uniqueInstance == null) {
 $unqiueInstance = new Singleton();
}
  • Return the uniqueInstance.

Class diagram of the singleton class

Singleton is just one class. Always a loner!

Singleton Pattern in PHP
Singleton Class

Complete Architecture | Singleton Design Pattern in PHP

Singleton Design Pattern in PHP

The following code shows the singleton pattern in PHP.

Code | Singleton Design Pattern in PHP

<?php
class Database {
 
    private static $dbInstance = null;
 
    private function __construct() {}
 
    public static function getDBInstance() {
        if(self::$dbInstance == null) {
            self::$dbInstance = new Database();
        }
        return self::$dbInstance;
    }
}
 
function main() {
 
    $databaseInstance = Database::getDBInstance();
 
    $databaseInstanceAgain = Database::getDBInstance();
 
    if($databaseInstance == $databaseInstanceAgain) {
        echo "Both the instances are the same";
    }
    else {
        echo "Both the instance are different";
    }
}
 
main();
 
?>

Output | Singleton Design Pattern in PHP

Both the instances are the same

Pros and Cons of the Singleton Pattern in PHP

ProsCons
Ensure that only a single instance exists.It violates the Single Responsibility Principle if the Singleton class has other roles too.
Provides global access to the singleton object.Whichever module uses the Singleton is tightly bound to it. Any change may require changes in these modules.
Supports lazy loading. The application initialises it lazily when needed.It is vulnerable to race conditions in a multi-threaded environment unless catered for.
Sub-classing it may not work as intended. You may need to look for workarounds.
Better paradigms like dependency injections usually win over Singletons.

Where is the Singleton Pattern Used?

  • Use it if you want to have only one class instance that has to be accessible globally.
  • Use it if you want to lazy load instances without diving into complexities.

Frequently Asked Questions

What type of design pattern is the singleton?

Singleton is a creational design pattern that ensures that only one instance of an object exists and is accessible globally. It uses a Singleton class with a static function that initialises the instance once and returns it when the application calls it.

Is singleton pattern thread safe?

No, the singleton is not thread-safe by default. The static function is vulnerable to race conditions in a multi-threaded environment. Threads can create the instance more than once, defeating this pattern’s purpose.

How to make singleton thread safe?

 There are different solutions, and one of the easiest ways is to initialise the static variable at class loading, sacrificing the lazy loading that was a benefit of using the singleton. Another option is to use synchronisation and method-level locks but be mindful of the performance overhead that comes with these locks.

Why is singleton an anti-pattern?

Design pattern promotes principles that are based on flexibility and loose coupling. The Singleton class couples tightly to the modules that use it, and thus polymorphism is usually ruled out of the equation, thereby compromising flexibility.

It is also difficult to unit test because the private constructor won’t permit sub-class mocks, and together with the problem of tight coupling, the application’s unit test may not work as intended.

On top of that, it is not safe in multi-threaded environments unless you use mutex locks or synchronisation, which affects the performance and increases your application’s complexity.

Is singleton bad?

Not necessarily if used in moderation. It does provide convenience if you want more control over the application’s resources. However, better alternatives like dependency injections may win over singletons. You may have to move away from singletons because convenience may not be desirable if that hurts your codebase in the long run.

Using the Singleton Pattern in PHP Today

That’s all about the singleton design pattern. As a recap, the singleton pattern is a creational design pattern that ensures a global variable is initialized only once in a program and is shareable globally. Cool as it sounds, it comes with some downsides too.

One of the downsides is the tight coupling between application modules and the singleton class. Besides, it could violate the single responsibility principle if it does more than care for the unique instance. For instance – the Database class with CRUD methods.

Singletons are not thread-safe, so you have to have either synchronisation or locks to prevent race conditions. If you’re unwilling to give up the performance hit by using locks and syncs, trade-off with the lazy loading feature and let the static variable initialise at class loading. 

Moreover, try to explore alternatives like dependency injections. Though singletons are not inherently bad, using them in excess can cause problems for you.

So, that’s all about it. Hope you have enjoyed it. Stay tuned for more at FuelingPHP.

Books on Design Patterns

Want to learn more about Design Patterns? There are many great resources online. We recommend the following books for your collection as they both can teach you the theoretical and the application of using design patterns in your day-to-day programming. Feel free to use the following Amazon affiliate links if you’d like to purchase them and a way to support our efforts.

Design Patterns: Elements of Reusable Object-Oriented Software

Design Patterns: Elements of Reusable Object-Oriented Software book

This is the book that started it all. I believe that every programmer should have a referenced copy to this book at some point in their career. There have been many updates and excellent newer content through the years, but this is a classic. It still stands the test of time and is just as relevant for today as it was in the original printing in the 90s.

Check it out on amazon

Learning PHP Design Patterns

This is an excellent book to go beyond the theory and apply it to writing good PHP code. Learning PHP Design Patterns is published by the popular O’Reilly media company. O’Reilly consistently publishes some of the most useful reference material related to software development. They are known to provide materials that thoroughly cover a topic in a way that is simple to understand. I recommend this book to every PHP developer.

Check it out on amazon

Design Patterns in PHP Learning Series.

This article is part of our series of design patterns in PHP. We are going through all of the patterns and showing how they can help you build better applications. Browse through our full list of patterns below.


Article Categories

Article Tags

© 2023 Confident.Systems