This site has a lot of object-oriented programming articles. Most of them focus on solving WordPress problems using object-oriented programming. This is great when you’re comfortable with object-oriented programming.
But most WordPress developers aren’t that comfortable with it. (You’d think there’d be a book on that or something.) It’s one thing to read about basic concepts like encapsulation and inheritance. It’s another to put them in practice. There are a lot of obstacles that you have to overcome.
One of these obstacles is the proper use of the static keyword. Static methods are a great object-oriented tool to use. But, like all good things, we can also abuse it if we’re not careful.
This happens a lot more in the WordPress development world than anywhere else. And there are good reasons for that. We’ll look at why that is and what you can do about it.
What is the static keyword?
The static
keyword is a something that you only use with object-oriented programming. You use it when declaring class methods and properties. This allows you to access them without needing to instantiate the class.
class A_WP_Class { /** * Actions that A_WP_Class hooks to. * * @var array */ private static $actions = array('wp_loaded'); /** * Get the actions that A_WP_Class hooks to. * * @return array */ public static function get_actions() { return self::$actions; } } A_WP_Class::get_actions();
Above is a small example demonstrating how the static keyword works. The A_WP_Class
has a static actions
property and a static get_actions
method. And below is how we’d call the get_actions
method without instantiating A_WP_Class
.
You’ll notice that you can still use visibility keywords with the static
keyword. The actions
property uses the private
keyword. This means that you can’t access it from outside A_WP_Class
. You have to use the get_actions
method.
And speaking of the get_actions
method, you might be wondering what the self
does in it. This is the static version of $this
pseudo-variable. It’s a shortcut to access static class properties and method for the class that you’re in.
Static variables
It’s worth mentioning that there’s another well-known use for the static
keyword: static variables. Unlike static methods and static properties, static variables have nothing to do with object-oriented programming. They’re variables that don’t persist the same way as normal variables.
In normal circumstances, PHP erases variables once it leaves a function or method. But when you define a variable using the static
keyword that tells PHP not to erase the variable. The next time that PHP enters that function or method, it will use the value that was there when it left earlier.
function increment() { static $counter = 0; echo $counter; $counter++; } increment(); // Echoes "0" increment(); // Echoes "1" increment(); // Echoes "2"
The increment
function above is pretty much the standard static variable example. We have the counter
variable that we defined as static. We echo the current counter
variable and then we increment it.
We initialized the counter
variable with a value of 0
. But what does that mean when you use a static variable? It tells PHP that the first time that it encounters the counter
variable to give it the value of 0
.
This will only happen the first time that we call the increment
function. But after, the counter
variable will exist and PHP will use the value stored when it was last in the function. That’s why the following calls to increment
don’t echo the initial value of 0
, but 1
and 2
.
WordPress and the static keyword
But why are WordPress developers that attracted to the static
keyword? There are a few factors at play here. And combined they are what makes the static
keyword a natural choice for them.
WordPress’s procedural programming legacy
WordPress is an old piece of software. (Especially if you count the b2 years as well!) Back then, PHP didn’t support object-oriented programming that well. Instead of using it, WordPress developers used the procedural programming style. (This made a lot of sense at the time.)
At its core, procedural programming relies on functions working together to solve problems. That’s why WordPress for most of its life WordPress only had functions and didn’t use any classes. And that’s why most WordPress developers still use functions as well.
Namespacing in WordPress
This brings us to the practice of using namespaces in WordPress. This is an important aspect of plugin and theme development. Here’s how the codex describes the practice for WordPress:
All the functions in your Plugin need to have unique names that are different from functions in the WordPress core, other Plugins, and themes. For that reason, it is a good idea to use a unique function name prefix on all of your Plugin’s functions. A far superior possibility is to define your Plugin functions inside a class (which also needs to have a unique name).
The highlighted section is what we want to focus on. Let’s imagine that you’re a WordPress developer who only uses functions in their code. That statement doesn’t tell you to stop doing that. It just tells you to put your functions in a class.
Now, let’s continue to put ourselves in that developer’s shoes. They need to use a class but don’t know object-oriented programming that well or at all. They want to keep using functions like before.
What do they do? They use the static
keyword! In their situation, a static method isn’t that different from a regular function. There’s no need to deal with instantiation or any other messy object-oriented stuff. Perfect!
WordPress isn’t object-oriented programming friendly
And why doesn’t that WordPress developer know how to use object-oriented programming that well? It’s because WordPress makes it hard to use it. Most of its APIs like the plugin API don’t translate well to object-oriented programming.
This reinforces the idea that the static
keyword is the correct way to go. You’re programming the way WordPress intended you to. But you’re not any closer to using object-oriented programming in a way that makes sense.
How to use the static keyword
Alright, so we have a better idea why WordPress developers use the static
keyword. We know that they’re not using it the way that we should. But what’s the correct way of using it?
The role of a static method
To begin, we need to take a look at the static method. So far, we’ve talked a lot about the static
keyword. But, in practice, most WordPress developers are using it to create static methods.
We know that a static method (like a static property) doesn’t need an instance of a class to be accessible. This should also define the job of a static method. It should be a job that doesn’t need an instance of a class either.
class Post { // ... /** * Sanitizes the given text by removing or encoding dangerous characters. * * @param string $text * * @return string */ private static function sanitize($text) { return strip_tags($text); } }
The sanitize
method above is a good example of such a job. We need it to sanitize text for our Post
class. That said, it has no need for instances of it.
Everything should be stateless
But we don’t have to stop our description of the job of a static method there. There’s another important quality to good static methods. They’re stateless.
What does stateless mean? It’s a fancy way of saying that the static method never remembers anything. You can call it as often as you want and the result is always the same.
Both the get_actions
and sanitize
static methods from earlier are examples of stateless static methods. The get_actions
static method always return the same array. And the sanitize
static method always returns the same value for the same input.
class Counter { /** * Current counter value. * * @var int */ private static $count = 0; /** * Increment counter by 1. */ public static function increment() { self::$count++; } /** * Get the current counter value. * * @return int */ public static function get_count() { return self::$count; } }
Meanwhile, the Counter
class above is an example (another counter example!?) of a class that uses a stateful (it’s the opposite of stateless) static method. You can’t guarantee that the get_count
static method will always return the same value. That’s because increment
static method increments the counter
static property. This changes the state of the Counter
class.
Avoid using static properties or variables
This is more or less a natural conclusion to the stateless requirement that we just saw. You should be wary of using static properties or variables. There are uses for them, but they’re not that common.
If you’re using a public static property, you should try to use a constant instead. That said, this isn’t always a valid solution. If you want to keep things private like we did with the actions
static property, a constant doesn’t work.
class A_WP_Class { /** * Get the actions that A_WP_Class hooks to. * * @return array */ public static function get_actions() { return array('wp_loaded'); } }
While our initial version of A_WP_Class
was stateless, there was no reason to use a private property like we did. We could have just put the actions
array as the return value of the get_actions
static method like we did above. This would ensure that it always remains stateless.
Moving away from the static keyword
Before we proceed into this section, let’s be clear on something. There’s no magic bullet that you can use to ween yourself off the static
keyword. It’s a design problem which means that it varies from situation to situation.
Now, this isn’t a reason to despair. But it won’t be a walk in the park either. With that in mind, let’s look at what you can do to reduce your reliance on the static
keyword.
Embrace object-oriented design
With the exception of static variables, the static
keyword is an object-oriented programming tool. If you want to use it well, you have to be willing to program in an object-oriented way. This means building classes that are more than just containers for your procedural functions. For that to happen, you need to start designing classes that solve specific WordPress problems.
The plugin API is an example (if not THE example) of a WordPress problem that comes up over and over. We mentioned earlier that it wasn’t object-oriented programming friendly. That’s why you often see WordPress code that uses static methods like this:
class A_WP_Class { public static function do_something_on_init() { // ... } } add_action('init', array('A_WP_Class', 'do_something_on_init'));
Yes, the do_something_on_init
static method is inside the A_WP_Class
class. But you register it to the init
hook outside the class. There’s nothing preventing us from turning the do_something_on_init
static method into a regular PHP function.
Learning to make tradeoffs
There are different ways to move away from code like this. You can design the ability to register WordPress hooks into the class itself. Or you can design a system to manage everything.
And those are just the solutions that we’ve explored here. There are others out there as well. And, in the end, you have to pick which one you want to use.
That’s because there’s no perfect solution to this problem or any WordPress problem. Each solution has its tradeoffs. You have to decide which solution fits your situation best.
Focus on the class’s job
Of course, making this transition to object-oriented design is neither quick nor easy. (That’s why this site exists after all!) But there’s a concept that you can use right away to help you with this transition. We call it the single responsibility principle.
The single responsibility is an object-oriented design principle. It’s part of the larger design principle called SOLID. (It’s the “S” in SOLID.) It says that, when you design a class, it should only have one job.
Why is this concept so useful compared to others? It’s because it forces you to think about the job of each class that you create. This is a common struggle when you’re getting started with object-oriented programming.
namespace MyPlugin; class Utilities { /** * Check if the plugin is active * * @return bool */ public static function is_plugin_active() { // ... } }
For example, a class like Utilities
doesn’t have a job. It doesn’t solve a specific WordPress problem. It’s the name that you’d give to a container for procedural functions like is_plugin_active
.
Finding good class names
Meanwhile, in the following single responsibility principle article (it’s worth a read!), there are no classes with names like Utilities
. Instead, there are classes with names like AdminPage
and Shortcode
. These class names are much more descriptive.
This reflects the desire to design classes that solve specific problems. Because of that, each class has a job. And you can get a good idea of that it is just from reading its name.
namespace MyPlugin; class Plugin { /** * Check if the plugin is active * * @return bool */ public static function is_active() { // ... } }
The Plugin
class has a bit of a redundant name considering the namespace. That said, its name is a lot clearer than Utilities
. We have a much better idea of what it represents from an object-oriented perspective.
We can tell that it’s a class that represents the plugin as a whole. In turn, we know that it should contain methods that solve plugin related problems. Such as answering the question “Is MyPlugin active?”. Which is what the is_active
static method does.
This helps with the static keyword too
But do we need is_active
to be a static method? That’s not always an easy question to answer. (More often than not, the answer is “no”.) That said, this is also something that the single responsibility principle can help you with.
You can use it to determine if you should use the static
keyword or not. The trick is to look at it within the context of the job that your class has to do. There are some elements of a class’s job where the keyword
makes sense. (For example, interacting with the plugin API.) There are others where it doesn’t.
So does the is_active
method need to the static
keyword to help the Plugin
class do its job? Well, if its job is to represent the plugin itself, it should track whether it’s active or not. This means that it needs to a way to track that active state.
This is a stateful behaviour. And, like we’ve seen before, a static method should be stateless. This means that is_active
shouldn’t be static.
namespace MyPlugin; class Plugin { /** * Flag to track if the plugin is active. * * @var bool */ private $active; /** * Check if the plugin is active * * @return bool */ public function is_active() { return $this->active; } }
Here’s how the is_active
method could look like without the static
keyword. We have the active
internal variable which tracks whether the plugin is active or not. And the is_active
method returns the current value of that variable.
This is a pretty simple example. In practice, the job of a Plugin
class can be pretty complicated. That said, you can see how the single responsibility principle can help you with the static
keyword.
Use this site as a resource
This last suggestion might seem like a lame plug, but it’s not! We mentioned earlier that you need to embrace object-oriented design to move away from the static
keyword. Well, this is one of the main topics covered on this site.
That’s why this article has links to over a dozen articles already. But there are even more for you to read. These are articles are an important resource that you need to leverage.
Most of these articles show you how to solve WordPress problems without using static methods. But some of them also show you the opposite. They teach you about WordPress problems where static methods are the correct tool to use.
It’s a mindset change
There’s no question that moving away from the static method is a challenge. You can’t do it without changing your programming mindset. And that’s never easy for anyone.
That’s why you should see the excessive use of the static
keyword as a sign. It’s telling you that your mind still hasn’t made the transition yet. You’re still thinking in a procedural way.
This is nothing to feel ashamed of! (It might even be where you want to be.) But, if your desire is to use less static methods or properties, then your path is clear. You have to move away from procedural programming.
P.S. If you have a static method or property that you don’t know how to remove, feel free to ask how in the comments below. I’ll do my best to help out!