Software development is about repeating yourself intelligently by using functions to encapsulate repetitve code, saving you the hassle of writing it out each time. This doesn’t just mean finding a repeatable pattern and going with it, it’s important to find the right pattern. That is where PHP design patterns come into play.
While we often think of this in terms of choosing to write a function or class, or to import a library, this approach also extends to application architecture. The architecture of a framework, CMS, plugin, theme, class, or system is often described as conforming to a pattern.
Being aware of the classic software PHP design patterns and architectures as well as common patterns employed in WordPress can be very instrumental in helping us write better code.
Event Driven Vs. Model View Controller
WordPress uses an event-driven architecture, in which there are hooks in the core software and plugins and themes that act as events. When WordPress encounters a hook, it executes all code “hooked” to that event.
This loosely conforms to the publisher/subscriber pattern where WordPress or a plugin or theme “publishes” an event with apply_filters() or do_action() that can be “subscribed to:” with add_filter() or add_action().
JavaScript runs in the browser using a similar event-driven approach. In JavaScript, we add event listeners to happen at specific events that are either triggered by page loading, such as window.onload() or based on user interaction with the browser such as a click event.
The event-driven architecture that WordPress and in-browser JavaScript use is fairly linear which makes it easy to understand. It can be summarized as “when this happens, do these things.”
The Model View Controller (MVC) pattern is not as easy to understand because it describes a real-time, circular relationship between the user and the application. There are many variations on the MVC pattern but in general, there are three parts: the view, controller, and model.
- The view or template defines the visual representation of the data, based on the current state of the model, and can change based on user input.
- The controller is the intermediary between the view and the data source or remote API. It also updates the model based on your interactions with the view and remote API.
- The model is the current set of data, defined by the controller and displayed by the view.
In general, an application, framework, or language using MVC architecture is more difficult to understand than one using event-driven architecture. Neither is “better” or “more powerful,” but they are different and suited to different uses.
There are a few frameworks that have been created on top of WordPress that implement the MVC pattern. That’s great when they fit a specific need, however, it is just important to keep in mind that they are MVC on top of an event-driven architecture.
Useful PHP Design Patterns
WordPress’s event-driven architecture by itself is not a software pattern. But it is implemented using the publisher/subscriber variant of the observer pattern. It’s not always a perfect match for the textbook definition of those patterns, but it doesn’t actually matter.
Learning about or using software PHP design patterns isn’t about scoring points for your impressive knowledge of the subject or application of that knowledge. Instead, understanding these patterns is about helping you use them when appropriate and knowing whether or not they are the right solution to a problem.
It also helps in reading other people’s code, which is important for improving your skills and helping you integrate it or debug it. Identifying a common PHP design pattern helps you make sense of the code you are looking at.
I’m not going to cover all of the software design patterns. Instead, I want to look at two formal patterns that are important for WordPress developers. I also want to talk about some patterns that are not formal, but are used a lot in WordPress.
The Singleton
The singleton pattern is very common in software development and in the development of WordPress plugins — however, it can be overused in the development of WordPress plugins.
The point of the singleton pattern is to ensure that there is only one instance of the class that implements it. In PHP, by default, any class can be instantiated any number of times. For the most part, this is great as it allows for using classes to create multiple objects with the same structure that represents different data.
But what about a class that is designed to load a plugin or application? Why would you want that to run twice? You probably only want one instance of that class. Or what about a class that builds an object that holds a plugin or application’s configuration? Again, only one instance of that class makes sense.
You’ll only need a single instance of the class, thus the name.
The singleton works by declaring the class constructor as private or protected. In this pattern, a private or protected static variable is used to hold the class instance. Then a public static method is used to retrieve that variable. Before doing so, it checks if that variable is null, and if so, it instantiates the class and stores the instance in that variable.
Here is an example:
<?php class singleton_example { /** * Holds class instance * * @access private * * @var singleton_example */ private static $instance; /** * Private constructor to prevent new instances. */ private function __construct(){ //feel free to do stuff that should only happen once here. } /** * Get class instance * * @return singleton_example */ public static function get_instance(){ if( null === self::$instance ){ self::$instance = new self(); } return self::$instance; } }
Because of the private constructor, you can not access this class using the new keyword like this:
$object = new singleton_example();
This would cause PHP to call a private method, which is illegal. Instead, you would get the single instance using the get_instance() method:
$object = singleton_example::get_instance();
Now the variable $object contains the instance of the class and you can use it to call non-static methods of that class.
The above example is fairly typical for WordPress since it supports PHP 5.2. In some cases, you may wish to subclass a class that implements the singleton pattern. There are not a lot of cases where you would want to do this, but you can using late static bindings:
<?php class singleton_example_two { /** * Holds class instance * * @access protected * * @var singleton_example_two */ protected static $instance; /** * Protected constructor to prevent new instances. */ protected function __construct(){ //feel free to do stuff that should only happen once here. } /** * Get class instance * * @return singleton_example */ public static function get_instance(){ if( null === static::$instance ){ static::$instance = new static(); } return static::$instance; } }
This example is similar but uses protected instance variable. It also replaces the self keyword, with the static keyword to ensure that PHP is referring to the current instance, not the parent instance when subclassing.
Keep in mind that singletons have a lot downsides and are overused in WordPress. That doesn’t make them bad, but be careful. A singleton often makes sense for the class of a plugin that is responsible for loading a plugin.
Your plugin may need a single instance of a class, but others integrating with your plugin or add-ons for your plugin may need their own instances.
Often times, WordPress plugins have one main class with a singleton that adds an instance of many other classes as properties of it. This allows them to avoid multiple singletons, while having the benefit of easy access to a specific instance of specific classes.
Another case where singletons get misused are classes that have no functional reason to be instantiated multiple times, but there is no harm in doing so. Often times, these are classes that don’t really represent a data object, but are a collection of related functions. Declaring all methods of these classes static can simplify things dramatically.
The Factory Pattern
The factory pattern is not used a lot in WordPress, but it is worth understanding as it makes complex systems that involve many separate classes explicit. A class implementing the factory pattern is designed to construct an object or an object of other classes. That’s why we call it a factory, it creates other objects.
Here is a simple example of a factory example that shows how it works. This basic factory is used to construct instances of the WP_Post class via a variety of means:
class post_factory{ /** * @var WP_Post */ protected $post; public function __construct( $post = null ) { if( is_a( $post, 'WP_Post' ) ){ $this->post = $post; }elseif ( is_numeric( $post ) || is_a( $post, 'stdClass' ) ){ $_post = get_post( $post ); if( is_object( $_post ) ) { $this->post = $_post; } }else{ $this->post = get_post(); } } public function get_post(){ return $this->post; } }
This is a very simple example, and might be an overly complicated way of ensuring a variable is really a WP_Post. That said, it limits having to repeat validation code all over the place while safely ensuring a WP_Post object, a post ID, or WP_Query args really representa WP_Post object.
Again, this is way too simple to be really useful, and shows a downside of the factory pattern. The extra overhead that might not be worth it. But, as in this example, it can be used to introduce validation of inputs, which might be worth it. Carl Alexander has an excellent article on designing a class to manage WordPress posts that is worth reading when thinking about a factory like this.
But there are many cases where it might be worth it and is a great way to create a system that creates multiple parts of the application from a single configuration.
For example, when we add a REST API endpoint or set of routes, we normally define the fields for those endpoints in the class that handles the route those endpoints are a part of. But what if we needed that configuration elsewhere? What if we wanted to inject that configuration into an endpoint generator as well as other generators?
That’s when we would use a factory or other factories. I recently published a WordPress REST API endpoint generator that implements a factory pattern. While it is useful on its own, I am also working on a library to consume the same configuration but will create a Backbone-generated interface that uses those endpoints. Since the configuration is loosely tied to the code, I hope to make it adaptable to generating the UI in Angular, and also adopting the Fields API spec once it is finalized.
Another place where factories could be useful is plugin add-ons. Often times plugins have similar add-ons that use the same hooks and employ a lot of repetitive code. One of the uses for a factory pattern would be to automatically setup all of those hooks.
WordPress Core Globals
One of the reasons to use a singleton PHP design pattern is that it avoids having to use a global variable to store an instance of a class. A singleton introduces a state that is like a global into an application, without using a global variable.
PHP global variables are completely mutable. They can be unset, or redefined at any time. We all agree not to ever change the global $post variable in WordPress to an array, but we can. There is nothing illegal about changing the global $post to a random array or unsetting its post_title property. The next time it is accessed, that’s when the problems will manifest, possibly as a fatal error.
WordPress core doesn’t use singletons. I can’t say for sure, but it is likely an artifact of WordPress and its predecessor b2/cafelog originating before static properties were introduced in PHP.
Instead, WordPress puts many class instances into a global variable. These classes tend to have a public constructor. In the case of WP_Rewrite, which is strongly tied to the saved rewrite rules, there is probably no chance you would ever want an instance of WP_Rewrite other than the one in the global $wp_rewrite.
If WordPress were written today, WP_Rewrite would probably implement the singleton pattern. Instead of:
global $wp_rewrite; $wp_rewrite->flush_rules();
We would probably use:
WP_Rewrite::get_instance()->flush_rules();
But, that might be an over use of the singleton PHP design pattern, maybe there would be one main WordPress class, that had a singleton and held an instance of WP_Rewrite, WPDB, WP_REST_Server, etc.
The global $wp_rewrite is pure technical debt that occurs when a project is over ten years old and is committed to not break backwards-compat. And let me be clear, being more “technically correct” is not, in my mind, worth breaking almost every WordPress site.
The use of globals in WordPress for classes that have a “main instance” but can be reused makes a lot of sense. For example, there is a global $wp_query object that holds the main query based on the current request.
This allows us to call the instance of WP_Query for the current request, and also make our own instances of WP_Query for other queries. If WP_Query used a singleton, we would have to write our own SQL queries whenever we needed to do multiple queries for posts in the same request, which would be terrible.
Yes, there are better ways to store that main query, if your framework isn’t over 10 years old to store, what we call the main query. My point isn’t to put down WordPress. My point is to identify a pattern we should look at because it helps us understand WordPress. Also, it helps us see how we could do better in our own work.
Why?
Again the point of this isn’t to impress yourself or your friends with the ability to identify and implement common PHP design patterns. No end user is going to go to a WordPress site and be impressed by the sparing, yet sensible, use of the singleton pattern, or the implementation of an MVC framework somewhere in the stack.
But, if learning to identify these patterns can help you better understand what’s going on in other people’s code you have to work with or helps you write better code, or better conceptualize the system you are working in, then you should be able to advance as a developer.
2 Comments