I’m perhaps more versed in front end development, but I often have to add custom functionality to the themes I build. And usually I’ll just drop these in my theme’s functions.php file. And usually, these get written in procedural. It’s quick and easy, and depending on how complex the task is, it’s all that’s necessary.

But there are some problems with this method. Function names can conflict with pre-existing names in Core or in other plugins.

And when a task gets complex, we can can end up with a very long page of code, where it’s difficult to separate and organise concerns.

OOP allows us to contain all the functions necessary for tasks within classes. and we can instantiate an object from the blueprint in the class, and set variables for each instance. This is quite powerful, and labour/code-saving.

And so long as the root classes use names that don’t conflict (usually by adding a prefix such as xyz_[function_name]), all the functions within can use whatever names you choose safely. And it is recommended to use the kind of function names which would have otherwise caused conflicts if written procedurally. Because those function names tend to be shorter and more readable.

Another advantage to developing in OOP, is you’ll be able to extend or expand your plugin with greater ease on into the future. Simply because it scales better than procedural – because it’s more organised.

There is a debate over the best method, OOP or procedural, and it seems that different cases would one or the other, and there is also talk of a 3rd way in “functional programming”. However, there is a strong sentiment that being able to OOP means more organised, safe and maintainable code. The tradeoff is the up front work required to plan and setup in OOP, relative to that required for procedural.

If you’re familiar with using basic php functions, but don’t know about using OOP, I recommend this TutsPlus OOP tutorial, and well as Alecaddd’s plugin development series (at least up to part 10). With that, you should be able to get going, and articles you read on OOP from then on should make a lot more sense.

LET’S BEGIN!

With that in mind I thought to set about building a simple plugin using OOP. I often include code in my themes which removes, hides, and disables anything to do with the WP comments feature. As quite often the sites I build are not blogs or just simply don’t require a comments system. OOP is perhaps overkill for such a simple set of tasks, but this is a good opportunity to see what is required at bare minimum to make a functional OOP based plugin.

The code I want to use to for my plugin has been around since at least 2013 when Matt Clements added this Gist to GitHub. But it’s always shown in procedural. We’ll be making it OOP.

I started out by downloading the excellent WP Plugin Boilerplate by Tom McFarlin and Devin Vinson. Actually i sed the plugin generator that uses the boilerplate at wppb.me. This provides an automated way to quickly set the plugin name, slug, uri and author details throughout the plugin directory.

The boilerplate is set up using OOP out of the box. And straight away going through the initial code provided and the file structure we can see a clear separation of concerns, and a logical organised structure.

Opening up the root plugin file, we can see clearly functions for when activating the plugin, deactivating the plugin. Uninstall functions do not need to be referenced in this file as the uninstall.php file is relatively autonomous, speaking directly with Core. We also see a “require” referring to our main plugin file in the “includes” directory. This contains the main class, and calls to child classes.

From this file, one of the things we can learn straight away is the division between public-facing and admin-area functionality. With each getting their own class within separate directories. And each directory getting it’s own javascript and css asset folders. There are other things here, references to the i18n.php file which handles internationalisation, and a reference to the loader.php file. The loader registers all the hooks that will be found in your completed plugin with the WP API, making them functional. You probably won’t need to touch this file.

Most of the action, is going to happen in the main plugin file in the includes directory, and in the admin and public directories.

My plugin is especially simply and doesn’t require any public functionality, and doesn’t use any js or css at all. So straight away I can delete the public directory, and the js and css directories from my admin directory. So I end up with something like this:

That’s already trimmed the fat off. Inside my main plugin file in the “includes” directory, I’ve commented out or deleted references to the public directory, as well as to enqueuing any scripts or css files.

Now the plugin is ready for my custom functionality to be dropped in.

Procedurally, my code would normally have just gone into functions.php as follows:

function custom_function_name() {
  // code
}
add_action($tag,custom_function_name);

With OOP however, we are creating a blueprint (via a class) with all the functionality in it, that is then instantiated as an object. The blueprint to be instantiated, is the admin class. So in the admin class file, is where I put all my functions. The “add_action” part does not belong to the blueprint. Instead, it’s called on the instantiation, which happens in the main plugin file (in my case, class-comment-crusher.php).

private function define_admin_hooks() {
	$plugin_admin = new Comment_Crusher_Admin( $this->get_plugin_name(), $this->get_version() );
	$this->loader->add_action( 'admin_menu', $plugin_admin, 'comment_crusher_disable_admin_menu');
}

In the code above, you can see where we have a variable $plugin_admin, which is an instantiation of our class for all admin-area functionality. This line alon won’t do anything for us. But on the next line, we use that variable to do stuff. The next line refers to the mother class ($this is refers to the class the function is in), then uses the loader to process the custom action or filter.

That’s essentially all I needed to do to get this plugin done. You can access the full code on the GitHub repo here.