Before we get started, let’s go over a few things so that everyone is on the same page.
The single responsibility principle can be explained in the following way. The class you created should do one thing and one thing only. It should also have all the information it needs internally to do what it needs to do. This means that you should not be using globals.
Why is it so hard to do with WordPress?
At its creation, WordPress wasn’t designed with objects in mind. Developers built WordPress by giving it simple APIs that were easy to use. These were great for new PHP developers. Maybe that’s how you got into PHP and even programming. That said, they can be confusing when you’re trying to apply object-oriented programming concepts. This is especially true for the single responsibility principle.
Have you already started playing with object-oriented programming? If so, you might have done a plugin where all the code was in a class. It’s pretty common for developers to do that.
That’s because it makes it easy for you to namespace/prefix your code and prevent errors. It’s even recommended in the official WordPress documentation. But building your plugin this way is problematic. It leaves you with an enormous class containing all your functions.
Doing things this way doesn’t offer you any advantages over just using a function prefix. It also doesn’t follow the single responsibility principle. Your class has no purpose because it does everything.
Now that we covered some initial bases, let’s get into the meat of this. Let’s help you use the single responsibility principle to build a WordPress plugin. I am a big meme fan so we will creating a small WP Meme Shortcode plugin as an example.
So to create this plugin, you need to think about the tasks your plugin needs to do. In this case, you don’t have to worry about too much. For this, we will divide the tasks into four parts.
First of all, you need a class that acts as the entry point to your plugin. It’s the starting point for WordPress when it loads your plugin. It should handle the registration of all the components. It’s also in charge of fetching the information the plugin needs to function.
It’s important to point out that the job of the entry point is not to add all the hooks and filters for the entire plugin! This goes beyond the responsibility of this class. How to handle hooks and filters is important enough that it will get its own section further in the article.
I usually name this class Plugin. This might seem like a bizarre naming decision to you. But there’s a valid reason! The idea is that, if WordPress had to only be aware of one class, plugin would be the logical name to use in that context.
For now, our WPMemeShortcode_Plugin class is pretty much empty. We put a placeholder static method called load. It’ll load the plugin into WordPress for us.
You want a single class to have the responsibility of retrieving and saving options. This removes the need for the other parts of your plugin to handle the storage of their options. All they need to do is interact with your class to get the option they need.
When you only have a few options, creating a class for options might seem like overkill. So, if you had to fold that responsibility into another class, it should be the Plugin class. You should still practice splitting it off into a separate class even for small plugins.
* value does not exist.
* Checks if the option exists or not.
* Sets an option. Overwrites the existing option if the name is already in use.
We designed our WPMemeShortcode_Options class around a specific idea. It’s that we’ll store all our options in a single array. All our methods interact with it.
By using the settings API, it is quite straight forward to create a class to handle your admin page(s). The class would handle the registration of all the settings as well as the rendering.
* Adds the admin page to the menu.
* Configure the option page using the settings API.
* Renders the admin page using the Settings API.
* Renders the general section.
* Renders the size field.
If you have several admin pages, it would be appropriate for you to split each page into its own class. You could also use inheritance and put the code common to all admin pages in its own parent class.
In the same way as your admin page, your shortcode class will be interacting with the WordPress shortcode API. It will handle registering the shortcode and generating the output.
Whether you’re working on a WordPress theme or plugin, you have to use hooks and filters. It’s fundamental to WordPress itself. Now, if you’re trying to move forward in your quest for object-oriented supremacy, this is where you might be struggling. What do I do with hooks and filters when I use classes to contain my code?
Putting all the hooks and filters in the constructor.
Creating a new object. Using that object and registering all your hooks and filters outside the class.
Neither options is that great. Creating an object shouldn’t add the hooks and filters by default. There could be situations (like for testing) where you want to create the object without adding the hooks. By having code outside the class for hooks and filters, you’re robbing the class of a key part of its responsibility.
The better way to solve this issue is by using a static method as a custom constructor. The function creates an instance of your class and uses it to register the appropriate hooks and filters. This allows you to separate the registration your hooks and filters from the construction of your object. I normally call the function ‘register’ or ‘load’.
* Register the admin page class with all the appropriate WordPress hooks.
Beyond hooks and filters, static methods are a great way to isolate your code from WordPress. They allow you to handle a lot of WordPress functionality beforehand. This also goes back to the idea that your class should have all the information it needs internally. It should not rely on outside information to work.
* Load the plugin options from WordPress.
To be clear, you should use WordPress functions if they make sense inside your class. WordPress has tons of useful helper functions that you should make use off. That said, functions like ‘get_option’ don’t help your class do its job. That is why they are good candidates for extraction into a static method.
So this is quite a lot to digest. Maybe you have a headache at this point? You might even be wondering if it is worth the trouble. So If you got this far, I will leave you with a few reasons to care about the single responsibility principle.
Where do I put this function?
Where did I put this function!?
Oh God! What was I thinking!
You know you have! That’s why, if each class has only one job, it makes your code easier to understand and read for you and others. In most cases, you don’t have to wonder where you put a function or where you should put it. That decision is almost made for you.
By having your classes do only one thing, you’re making all your code more robust. For example, let’s say that every class is in charge of getting its own options. You decide that you have to many individual options, you want to use an array.
You would then have to track down all the code in your plugin and make the changes there. Each individual change could create a bug. Having a single class in charge of options means that you only need to make that change in one location.
Unit testing is not something that a lot of WordPress developers do (yet!). That said, when your classes specialize in one thing, they are easy to test and mock. This makes testing a lot less painful if you ever decide to do it. Using a static method as a constructor to isolate some of the WordPress functionality also helps with this.