The Singleton pattern is one of the most commonly used design patterns in object-oriented programming. It’s especially useful when you need a single, shared instance of a class throughout your application.
In this post, we’ll explore what the Singleton pattern is, how to implement it in PHP, and why it’s particularly useful in WordPress plugin development. We’ll also look at how to simplify its implementation using PHP traits.
The Singleton pattern ensures that:
This is ideal when a class:
Let’s say you’re building a WordPress plugin. You may have a class named Plugin
that sets up everything your plugin needs:
class Plugin {
public function init() {
add_action('init', [$this, 'bootstrap']);
}
public function bootstrap() {
// Run plugin logic
}
}
The problem? If you accidentally create multiple instances of this class, your plugin logic may run multiple times. That could cause duplicate hooks, performance issues, or unexpected behavior.
To prevent multiple instances, you might manually implement the Singleton pattern like this:
class Plugin {
private static $instance = null;
public static function get_instance(): self {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
$this->init();
}
private function __clone() {}
private function __wakeup() {}
public function init(): void {
add_action('init', [$this, 'bootstrap']);
}
public function bootstrap(): void {
// Plugin logic here
}
}
You would then use it like this:
Plugin::get_instance();
Now, the class is initialized once, and init()
is called on the first call to get_instance()
.
Without the Singleton pattern, you might accidentally write:
$p1 = new Plugin();
$p2 = new Plugin();
And both instances would register hooks — leading to duplicated behavior.
With Singleton, no matter how many times you call:
Plugin::get_instance();
You always get the same object, and your logic runs only once.
If you have multiple classes that follow the Singleton pattern — for example, Plugin
, Admin
, Logger
, Shortcodes
, etc. — repeating the same boilerplate in each class becomes tedious.
A better approach is to create a reusable Singleton trait:
trait Singleton {
private static $instance = null;
public static function get_instance(): self {
if (static::$instance === null) {
static::$instance = new static();
}
return static::$instance;
}
protected function __construct() {
if (method_exists($this, 'init')) {
$this->init();
}
}
public static function has_instance(): bool {
return static::$instance !== null;
}
public static function reset_instance(): void {
static::$instance = null;
}
private function __clone() {}
private function __wakeup() {}
}
Now you can use this trait in any class that should follow the Singleton pattern:
class Plugin {
use Singleton;
protected function init(): void {
add_action('init', [$this, 'bootstrap']);
}
public function bootstrap(): void {
// Plugin logic
}
}
This avoids repeated boilerplate while still getting the same Singleton benefits.
Benefit | Description |
---|---|
Centralized logic | All setup happens in one place |
Global access point | Use Plugin::get_instance() from anywhere |
Prevents duplicates | No risk of multiple hooks or DB calls |
Cleaner code with trait | No repeated __construct() logic |
Works well in WordPress | Especially useful for plugins using hooks and filters |
Avoid the Singleton pattern when:
In such cases, a service container or factory pattern is more appropriate.
The Singleton pattern is simple but powerful. In WordPress plugin development, it keeps your architecture clean by ensuring that key components only initialize once. Using a reusable trait makes your code more maintainable and consistent across multiple classes.
If you build plugins with classes like Plugin
, Admin
, or Shortcodes
, consider using the Singleton pattern to avoid repetition and confusion — and keep your plugin behavior stable and predictable.
If you found this article interesting, found errors, or just want to discuss about them, please get in touch.