In terms of updating the WordPress Widget Boilerplate (all of which is tracked in the develop branch), we’ve come a long way in terms of refactoring how it’s organized.
Thus far, we’ve:
- looked at how the WordPress Widget API provides an example of object-oriented programming,
- how we can use this API to determine object-oriented programming in other areas of WordPress,
- installed tools to help us evaluate the quality of the code,
- found errors that currently exist in the code in terms of modern programming standards,
- and began re-organizing the code base so that it fits with more modern practices.
Now we’re ready to start refactoring this code in a much more object-oriented manner.
So if you’ve yet to catch up with the previous posts (any of them, really), I recommend doing so because it’s going to take a little while to bring this up to date. There’s a lot of code to write an explain.
Let’s get started.
The WordPress Widget Boilerplate: Refactoring, Part 3
Arguably, the biggest problem with the Boilerplate is that everything is encapsulated within a single class.
Sure, there are some nice things like keeping our views separated from the server-side logic, but that’s about as far as it goes.
Other problems that exist just from looking at the code include:
- adding actions and filters in the constructor,
- having methods doing more than one thing,
- not having classes responsible for implementing things like registering dependencies,
- and so on.
In this post, we’re going to start the process of creating abstractions that we’ll eventually implement to break up the god-class-like nature of the Boilerplate as it stands.
This is going to be broken into several posts so that I’m able to provide a solid explanation as to why we’re doing certain things that we’re doing as well as explaining the examples behind it.
If I do it any other way, the series leaves out too much valuable information that’s applicable to other object-oriented programming practices.
What’s a Subscriber?
The WordPress hook system – that is, the actions and filters we have available – are based on an event-driven design pattern. This means that whenever something happens, an event, then WordPress will fire any other code that has subscribed to said event.
So when we register a function with a hook, we’re subscribing to the event. To that end, I’m a fan of creating subscribers for any given hook that we’re going to need.
On top of that, subscribers generally follow a consistent format. This means it’s really easy to create an abstract class that implements some of the consistent functionality and then allows the class implementing the abstracted class to focus solely on business logic.
Creating an Abstract Class
Before implementing the abstract class, let’s lay out exactly what it is that we’re going to do to create this.
- We need a property that represents the event to which we’re subscribing.
- We need a function to fire whenever the hook is fired by WordPress. Another way of thinking about this is we need a function to implement whenever a given action or filter is fired by WordPress.
- We need classes to implement the abstraction.
First, let’s define abstract classes. Straight from the PHP manual, we read:
Classes defined as abstract may not be instantiated, and any class that contains at least one abstract method must also be abstract. Methods defined as abstract simply declare the method’s signature – they cannot define the implementation.
In short, this means that we can’t actually create an instance of an abstract class. We can only instantiate classes thtat define the implementation.
This does not mean, though, that the abstract class can’t implement concrete things (such as the definition of a hook). But it means that there are certain methods that have no implementation.
Otherwise we’re just left with a basic class.
Make sense? Let’s take a look.
Creating an Abstract Class
Remember, because this is an abstract class, the concrete subscribers can be called something that identifies what they do (that is, they can call themselves anything that represents their purpose). And we’ll get to get to that.
But first, the abstract class. I’ll share the code then explain exactly what’s going on with it:
- Notice that the property we’ve created is protected. This is so that implementing classes can access it, but anything outside of it cannot.
- I’ve created a function for retrieving the hook that will become apparent later. Typically, I hate implementing functionality that isn’t immediately obvious, but this is something that’s important given where we’re headed.
- There is an abstract function called load. This is where any class that implements this function will house its business logic, as we’ll see momentarily.
- I like to document the purpose of the functions whene necessary so they are in one place and then let the implementing classes provide the documentation they need to provide in their implementation. You’ll see this momentarily, as well.
Now that we’ve got the abstract class in place, the last thing we need to do is make sure it’s placed in the proper directory and namespaced. If you’ve followed along starting with the previous post, then you’ve likely been able to guess where it’s going to reside based on the namespace in the code.
And if not, no worries. Figuring out namespaces and what not can take a little bit of time. So through these membership posts and these examples, it’s my hope that it becomes clear over time.
Creating Concrete Classs
The only thing that differs is the implementation of the load functionality which is exactly how this should work.
Given the abstract class above, now we need to create a class for registering stylesheets. Since we have two stylesheets, we’re going to be creating two classes:
- the first class will be responsible for registering the stylesheet for the dashboard and specifically for the WordPress widget’s page,
- the second class will be responsible for registering the plugin for the actual blog.
Let’s call each of the these AdminStylesheetSubscriber and PublicStylesheetSubscriber respectively.
First, the admin stylesheet subscriber:
Notice that this uses the get_current_screen() function that I’ve used in previous posts to make sure we’re adding dependencies only where necessary.
Obviously, we’ve yet to actually instantiate these classes. That’s coming later in the series.
Again, these classes can’t yet be instantiated but we’ll be focusing on that in an upcoming post.
Abstractions and Interfaces
Remember that abstractions and interfaces are different but are easily confused. Interfaces contain absolutely zero implementation. Instead, they provide a guarantee that any class that implements the interface will implement all methods.
This will become apparent, if it hasn’t already, the further we get into this series. In the meantime – and as per usual – don’t forget to check out the develop branch to see where we stand with the code.