Organising WordPress plugin/theme code: Part 1 – Prefixed Functions

Part 2 of this article is now out!

I’m sure a lot of you reading this will have developed a plugin or a theme before, and therefore know the single question that comes to mind every time you start a new project, whether it’s a plugin or a theme – how should you organise your code?

In short, there are three main ways to do this – prefixed functions, one giant class, or a complex class/worker class structure. In this first article, I’ll be introducing you to the most common method, and showing you a simple plugin that we’ll be implementing all three ways.

NB: When I talk about organising theme code, I obviously mean the code in functions.php – there only is so many ways you can code a page template.

Organising code? Hmph, a pro doesn’t need to!

Arrogance and lack of consideration for planning is unfortunately more common than not among semi-professional developers, and this also applies to me – if anything, I’m more on the extreme anti-planning side of the scale. However, whether you plan it or not, your code will end up being organised one way or another – even if it ends up disorganised (however strange that may sound) – because there simply has to be some way that you typed all this code into your file(s).

From my experience (and extended thought experiments) there are precisely 3 main ways you could’ve done that: Prefixed Functions, Single Class, or a Worker Class arrangement. I’m going to show you a simple plugin implemented in all three variations, of course accompanied by commentary lovingly sprinkled with sarcasm and bad humour.
NB: I coined all of these terms, as they seem as the best ones to describe these. If you have better suggestions, feel free to leave them in the comments!

The Plugin

Before I can start talking about ways of writing plugins, let me introduce you to the example plugin we’ll be writing three different ways in this article: Bacon Widgets Ultimate. Bacon Widgets Ultimate is a revolutionary plugin which facilitates the unthinkably difficult task of creating a “sidebox” anywhere a shortcode is inserted, which includes a specific block of text specified in the admin panel.

We’ll use some dead-simple CSS for the box, which will be included on every page to keep it simple:

View CSS

[css]div.bacon-widget
{
font-style: italic;
border: 1px solid #000;
float: right;
margin: 5px;
padding: 3px;
width: 40%;
-moz-box-shadow: 3px 3px 5px 6px #ccc;
-webkit-box-shadow: 3px 3px 5px 6px #ccc;
box-shadow: 3px 3px 5px 6px #ccc;
}[/css]

Yup, I put my CSS braces on a new line. Bite me.

We will store two options for our plugin: one to control the text displayed, and one to control whether or not the text will be encased in a strong tag. To be efficient, we’ll store both options in one WordPress option, bcn_settings, as an array:

[php]
$options = array(
‘display_text’ =>; ”,
‘bold_text’ =>; false
);
add_option(‘bcn_settings’, $options);
[/php]

The box will be displayed anywhere with the shortcode [baconwidget].

Prefixed Functions

Probably the most common of the three, also arguably the easiest to make an unintelligible mess of. Basically, it consists of picking a prefix such as bcn_wdg_ for a plugin called Bacon Widgets, resulting in lots and lots of functions with names such as bcn_wdg_init, bcn_wdg_echostyles, bcn_wdg_shortcode_echowidgets – you get the idea.

The disadvantages of this are almost self-evident – the most obvious of all being that code like that is quite ugly. The prefixes are quite redundant, and after a while it gets tiring typing them out in front of every goddamn function and variable you’re using. And if someone else picks the same prefix you’re using, you’re screwed. One could argue that this is also the case with classes, but what’s more likely to be thought of by two different people: shopcart_ or BaconShoppingCartPlus?

There are two advantages to this approach – one quite obvious, the other one less so. The obvious advantage is that it’s easy to write – there’s no fiddling around with boilerplate class code, or worrying about constructors and such. You just write your code and it’s done. When you hook something into WordPress, just use a string with the function name and presto! – the hook works.This approach is quite obviously best suited to small plugins with no more than 10 or so functions – it’s quick to write and not too hard to wrap your head around.

The other thing people don’t realise this approach allows them to do is separate the plugin code across many files. Using the magic of require_once, you can make your code a pleasure to maintain. You can easily have your main plugin file simply be a collection of include or require statements, including other files, each with a specific function. This makes things like finding an error, modifying specific functionality, excluding specific functionality or sharing code a breeze. Look at this example from one of my plugins – isn’t it beautiful?

[php]
<;?php
/*
Plugin Name: Photo Proof Review
Plugin URI: http://******.com
Description: Plugin facilitating the review, selection and sharing of photo proofs.
Version: 1.0.0
Author: Mateusz Jadczak
Author URI: http://wpandbacon.com
License: All Rights Reserved
*/

define(‘IN_PROOFREVIEW’, true);

//Check if we are called directly
if (!function_exists(‘add_action’))
{
echo &quot;Please do not call this file directly.&quot;;
exit;
}

//include modules
require_once(‘prf-css-js.php’); //Include plugin’s css and js
require_once(‘prf-install.php’); //Installation hooks
require_once(‘prf-ajax.php’); //AJAX functions
require_once(‘prf-account.php’); //Login/account page
require_once(‘prf-select.php’); //Photo selection page
require_once(‘prf-admin.php’); //Admin pages
require_once(‘prf-share_view.php’); //View shared album
require_once(‘prf-checkout.php’); //Checkout page
require_once(‘prf-fbenable.php’); //Theme hack

//Installation hook
register_activation_hook( __FILE__, ‘prfrv_install’ );
?>;
[/php]

Several things to notice here – the first being the prefixed files. If you try to go down the path of just calling the files admin.php, install.php etc, very soon you’ll run into a very weird problem, where you’ll get the core WordPress files being included into your code – a recipe for disaster!

Another is this little snippet:

[php]define(‘IN_PROOFREVIEW’, true);[/php]

and its complimentary

[php]<;?php
//Part of Proof Review
if (!defined(‘IN_PROOFREVIEW’))
die(‘Do not call this file directly.’);[/php]

in every included file. This is a must for any plugin spread out over multiple files, to prevent vulnerabilities where the files are called directly.

Bacon Widgets Ultimate prefixed functions style

Click here to download the source code for this style of coding. I didn’t really see the point in including the code here – this post is bloated as it is!

I do realise that the separation of functionality is perhaps over-the-top for this scale of a plugin, but hey, I’m only demonstrating the concept! Make sure you peruse the code, and familiarise yourself with the functionality, because this is the simplest way of writing this. Notice how easy it is to find a particular piece of code simply through the organisation of the files.

There isn’t a whole lot to say about this – this is your bog-basic way of writing a WordPress plugin. If you were writing a theme, it would be pretty much the same, with functions.php replacing your plugin.php file.

Next Thursday, we’ll look at the way most people tout as The Way to write WordPress code – as one, single class. We’ll look at why most people advocate it, and also at its shortcomings. The Thursday after that, we’ll look at the way that combines the best parts of both.

Stay tuned!

  • Pingback: Organising WordPress plugin/theme code: Part 2 | Wordpress & Bacon

  • http://www.workshopshed.com/ Andy from Workshopshed


    A class should contain the code and variables needed to do one task so often it make sense to have one class for a plugin. However if there are multiple things happening in the plugin e.g. a UI Widget, Background Scheduling, complex Admin UI then it makes sense to split this into multiple classes.

    • WPandBacon


      Exactly, and that’s what I’ll be advocating in the 3rd part of this article. Unfortunately, some things came up which mean I can’t really finish it off, but I hope to get it out soon.