WordPress Widgets: An Object-Oriented Approach

Years ago, I created the WordPress Widget Boilerplate aiming to be the following:

An organized, maintainable boilerplate for building widgets using WordPress best practices.

Since then, not much has changed regarding the Widgets API (which we’ll look at later in this post), but what I consider to be “best practices” has changed. Further, the degree to which I think this API is a solid example of introductory object-oriented programming in WordPress is high.

WordPress Widgets: The Widgets Boilerplate

It’s not because it uses a lot of object-oriented principles, it’s not because it uses modern standards (at least as far as modern PHP is concerned), but because it does use a few things that help us to recognize a few, say, signals regarding object-oriented programming in WordPress.

And this is something that shouldn’t be understated: If you’re looking for examples of object-oriented programming in WordPress, look for APIs that employ it.

Further, if you’re looking for ways to gauge you’re own level of evaluating a piece of code (let alone a code base) for the use of classes and some of the more advanced features of OOP, then why not have some sort of a litmus test to see how you’re doing?

WordPress Widgets: The Widgets API

And the Widgets API does just that.

WordPress Widgets: An Introduction

So in a smaller series than my last, I’m aiming to look at the Widgets API and to do a few things:

  1. show you the basic skeleton of a widget and why it’s object-oriented,
  2. discuss what things you should be able to notice and why,
  3. update the Widget Boilerplate directly on this site first and then push it out to GitHub,
  4. build a widget using the API with the boilerplate as the foundation for our work.

And in this post, we’re going to start with the first point above.

But First…

Before going into this post, I recommend reading the following posts:

  1. Two Pillars of Object-Oriented Programming: Part 1 of 2
  2. Two Pillars of Object-Oriented Programming: Part 2 of 2
  3. Abstract Classes, Part 1 – Abstracting Behavior
  4. Abstract Classes, Part 2 – Abstract Classes and Interfaces

Once done (or if you feel you already have a grasp on the topics), then we’re ready to go.

The Basics of the Widgets API

If you read through the handbook page on Widgets, you’ll see a lot of content. This is a good thing, but it’s not always the best move when trying to distill content to an audience such as yourself when you’re looking for practical, object-oriented advice.

So I’m going to pick out relevant parts from the API documentation and then apply it to the code we’re also provided.

What’s a Widget?

I think most of us who work with WordPress know what a widget is but it’s important to define the term so we’re all working off of the same idea. The handbook reads:

A widget is a PHP object that outputs some HTML. The same kind of widget can be used multiple times on the same page (e.g. the Text Widget). Widgets can save data in the database (in the options table).

With this in place, let’s take a look at the code of a custom widget, at least a stub of it, and see what we can glean as far as its object-oriented nature is concerned.

The Widget Class

Before we even look at the code, we know there’s going to be some level of object-oriented programming simply because the documentation tells us to do three things:

  1. Create your widget’s class by extending the standard WP_Widget class and some of its functions.
  2. Register your widget so that it’s made available in the Widgets screen.
  3. Make sure that your theme has at least one widget area in which to add the widgets.

In this post, I’m going to be focusing on the first point (though we’ll eventually get to how we introduce our widgets into a theme before the series is over).

So let’s lay out the code as it’s presented in the documentation and talk about what we can learn from it:

First, we notice that though we defined a class (which we can name whatever we want, my the way), it must extend WP_Widget. This means that in WordPress core, there is a WP_Widget class. You can view a well-organized breakdown of the source code on this page.

Secondly, the keyword extends indicates that we’re using PHP inheritance which is a core pillar of object-oriented programming.

Third, there are four functions that we must implement two of which require arguments. The functions that we must implement are as follows:

  • __construct() which is the basic class constructor. This is where we’ll need to make sure the parent class constructor is called, if there is one, and then we initialize whatever properties we deem necessary for our widget. We’ll take a look at this later in the series.
  • widget() is responsible for outputting the contents of the widget that the user provides using the interface in the administrative area. It accepts two parameters – $args and $instance. The $args parameter is the information to be rendered on the to the page, and the $instance is a reference to the instance of the widget (since multiple widgets can be rendered on a page).
  • form() displays the administrative interface with which the user interacts to guide what’s output on the front-end of the site. It also requires the $instance argument so the information provided is for the actual widget with which the user is working (versus all instances of the widget).
  • update() is used to save the values to the current instance of the widget. It accepts two arguments. The first is the new instance of the widget with updates values that the user has provided (think of updating the value of an active text widget) and the second argument is that of the old instance of the widget or perhaps the previous instance or perhaps “the instance that held the previous values.”

These four functions are required to implement as part of the Widget API, as part of inheriting functions from the extended interface, and to produce the basic functionality of a widget.

This doesn’t mean more can’t be added, but in good object-oriented fashion, it would likely be best to relegate that behavior into other classes. But we’ll take a look at doing that later in the series when we’re creating our own widget.

What Are The Key Takeaways?

To make sure I’m clear as to what would be understood from this post, it’s the following:

  • The Widgets API is object-oriented. It’s not just object-oriented because it uses a class (though that’s certainly a good starting point), but also because it inherits functionality build into a pre-existing base class.
  • Whenever we inherit behavior from a base class or a parent class, we’re getting pre-developed functionality for free. It’s a really great thing about object-oriented programming because it allows us to focus specifically on the programming logic that we wish to implement.

Imagine for a moment that you want to develop a widget but every single time you do, you have to write all of the functionality to hooks into WordPress to do all of the same, repetitive boilerplate functionality.

This is where inheritance and object-oriented programming come into play. The repetitive code is abstracted into a base class so it’s only written once and then the code we want to focus on is left up to for us to implemented.

All of the above is what should be understood when reading this initial pass at the source code for a basic, object-oriented API in WordPress.

What’s Next?

In the next post in this series, we’re going to look at the object-oriented nature of the Widgets API and what things you should be able to detect immediately by reading the code.

This is because it’s important to recognize certain object-oriented principles in practice and this is a good way to gauge if you’re able to do that or not. If you are, great! Then it’ll continue to help develop that muscle. If not, no worries – it still helps you develop that muscle.

And it will serve you well as we continue to get move more and more into object-oriented WordPress development through practical means.

The necessary theory has been covered. So let’s get started on actually putting it into practice.