WordPress is normally written in procedural PHP which makes it extremely easy to read, write and follow along with the code to figure out whats going on. However procedural code also has it’s share of downsides such as namespace errors and code organization problems. A few of these problems can be remedied by using object-oriented PHP. The benefits to object-oriented programming are:
- Namespace – You only need a unique class name, all the methods within that class can have very generic names
- Stateful – PHP keeps track of the state of interaction by setting values or variables that are stored for each instance of that object
- Private Methods/Variables – Keeps code more organized so that only certain methods are public for template files and others are used for internal operations
- Reusability – Object-oriented code is easy to reuse via extendability and because we can use our classes in more than one theme
Next we will will look at two different examples of traditional procedural PHP in WordPress followed by an object-oriented example. I feel look at an example of how to perform a common task will be the best way to see what the changes will look like going from procedural to object-oriented. I will use enqueuing Font Awesome as my example action.
Anyone who has poked around in the
functions.php file will most likely recognize the example below. This is the standard procedural method for hooking a function into WordPress when a hook is run. Let’s take a look at the code:
‘wp_enqueue_scripts’ hook occurs this code example will run our function which will add the Font Awesome style sheet to the scripts WordPress will load. It’s important you use this method to include scripts because WordPress will manage things and ensure no conflicts happen between any scripts. As you can probably see, this method is easy to read and to follow whats going on. In fact if you wanted to make it even more readable you could put the
add_action( … ) above the function call so it reads top to bottom.
Slightly Less Traditional Method
The example below is very similar to the example above except that rather than creating a function and giving it a name we will simply pass the
add_action( … ) an anonymous function for it to run. Please note that this will only work in PHP 5.3+.
As you can see this code example is very similar to the first example except rather than giving a method name as the second parameter in
add_action( … ) we give a anonymous function and include all the code for the function right there. This way we cut out a little bit of code and it’s almost more readable than the above example since it’s so obvious what is being run when the hook is activated – the function that is right there.
Finally we will look at an object-oriented approach to the same problem. There is a lot more code in this example but I’ll talk about how to organize everything after the example. Basically what we are trying to achieve is a theme class so that we can create a theme object that we can then use. It would make sense for the enqueuing of scripts to be in the constructor so that’s exactly what happens.
The first thing we do is create our class and constructor. In the constructor we call the
add_action( … ) method just like before, but the second parameter this time is an array. The first part of the array is the
$this variable which refers to the class containing the method. The second variable in the array is the name of the method we want to be run during that hook. To make sure everyone sort of understands what’s going on there I’m going to try to explain the basics of the
$this variable so if you already understand the concept behind it then skip ahead and we’ll get back to the example at hand.
The basic explanation is that you would call
$this whenever you want to access a method or variable of the current class. For example, we could have a class like the one below:
If you wanted to access the variable directly from somewhere else we could do something like this:
From the above example you can see that we can treat
$this exactly like a instance of an object would be treated but within it’s own class. That’s how I think of it anyways!
Back to the example, now that we understand what we’re doing (hopefully) with the
add_action( … ) call some of you might wonder why we aren’t just using an anonymous function again. The fact is that you probably could, but we are trying to use proper object-oriented standards so we’ll be putting everything in functions. This way the functions can also be called via an instance of the class – so its much more verbose to do it this way. The naming behind the function is one I learned about from others in the community; all action hook functions are prefixed with
action_ and all filter hook functions are prefixed with
In a real world theme our
action_wp_enqueue_scripts() function would obviously contain a lot more style sheets and scripts. We would also want to create a function for setting up the theme that gets called in the constructor, something like
setup_theme() function which would have all the
load_theme_textdomain( … ),
add_theme_support( … ), and
register_nav_menus( … ) calls we needed. That way all you need to do in
functions.php is create an instance of our class.
Next imagine if we moved all of the data related code into a plugin. Things like creating meta boxes and custom post types could all be put into the plugin and you could then switch out the theme without losing any of the data related code. This would obviously be separate from the the theme class you create which would contain all your design related code. In this way you can have these two classes working together but still being separate so either one can be switched out for another theme or another plugin. If you create all your WordPress sites like this then you will built up a huge code base that you can easily reuse for future projects and you’ll work that much more efficiently.
As always thank you for reading and please share it around as much as you can! Please feel free to put any suggestions or ideas for future tutorials in the comments section below.