How to make an object oriented WordPress plugin

If you’re thinking of creating a WordPress plugin, whether small or large, for your own use or the whole world to benefit from, it’s important to start right.  Most of the example code on the WordPress documentation shows the functionalities in a procedural layout, because that makes it easier to explain.  But best practice is to use modern programming techniques – classes, inheritance, closures, and so on.

This tutorial will take you through the process of creating a very basic WordPress plugin, but created the right way.  This is partly intended to be a helpful reminder to me next time I’m creating a plugin, but hopefully others will find it useful too!

What we’ll be making

This plugin will provide an options screen in the WordPress back-end for the admin to specify how many things he has.  On the front-end, we’ll use a shortcode to display a form to ask visitors how many things they’ve got.  We’ll handle the form submission, store the number of things the visitor has in our database, and then use another shortcode to display how many things we all have in total.

It’s a pretty lame plugin, really.  But it will allow us to go through the process of making an options page, creating shortcodes, using templates, and handling form submissions.

Step 1: Naming conventions

An important thing to decide before you even put fingers to the keyboard is what to call your plugin.  Even if you’re the only person who will ever use it, you need to be sure that someone else isn’t using the same plugin name so that you don’t run into issues later.  A quick search in the plugin directory will answer your question.  And remember that it’s about the internal name, not the display name; you’ll see what I mean in a moment.  If you’ve ever asked yourself how many Daves you know, you’ll understand why unique naming is important.

First create a folder under /wp-content/plugins/  with the name of your plugin, for example /wp-content/plugins/md-things-plugin/ .  The folder name should be unique in the entire WordPress plugin ecosystem.  In theory I suppose you could use a random string here, but that would just look weird, so don’t do that.

Next, create a PHP file in that folder with the same unique name, in this case md-things-plugin.php .  For clarity it’s important that the names match, not because WordPress will get confused but because you might, or another developer who looks at the code.

Step 2: The class

Here’s our first bit of code, in md-things-plugin.php.

The comment block at the top is important, as that’s what will be displayed in your WordPress plugins page to tell everyone what the plugin is.  Technically the plugin name here doesn’t need to be unique, but it helps you be sure which plugin you’re activating!  You can probably work out what the other comments are about.

Next, we create the class, again using that unique name.  We wouldn’t want to run into issues where other plugins are using the same class name!  We’ll create a __construct()  function, which we’ll put stuff into later.  And then, finally, we simply use a variable to create an instance of the class.  The variable itself won’t be used directly, but it’s a way of making sure the class is run.

Step 3: Activate and deactivate

The first thing you do when you install a plugin is activate it.  Some plugin don’t need to do anything when they activate, but if yours does then you’ll need to catch that event and do something with it.  In our case, our plugin will need to set up a database table to store the number of things visitors have.

First off, we only want to listen out for activation/deactivation when we’re logged in as an administrator, so we’ll use is_admin()  to conditionally check.  And we’ll use register_activation_hook()  to listen out for the activation event.

There are a couple of bits of magic here.  First, notice the array in the register_activation_hook()  call.  In the WordPress documentation the first example (which is the one people read first) just has a string containing the name of the function, but since we’re using an object oriented approach our function is in a class, and using array(&$this,'activate')  is the way to do it.  It’ll go off and find the public function activate()  in the current class.  Neat!

In the activate()  function itself, we’re using the global $wpdb  object, which is how we safely access the database.  I won’t go into too much detail here on how to use the WordPress database, you can look that up yourself.  But what I do want to highlight is the dbDelta()  function.  That looks at the SQL code we’ve provided, and applies it to the database.  If the table doesn’t already exist, it makes it.  So when the plugin is activated, that table will be created too, assuming it wasn’t there already.

For deactivation it’s pretty much the same deal, but using register_deactivation_hook() .  It’s up to you whether you do anything with the database you created on activation – you may want to leave it all there, or truncate the data, or drop the table completely.  Up to you.

Step 4: The options page

This step is a little more messy, in my opinion, but I’ll try to make it clear what’s going on.  Once again, we’re only interested in the options page if we’re looking at the back-end of WordPress, so we’ll add our listener in there.

The first action uses the same technique used before of sending the event to a function within our class; I’ll show you what goes in there in a moment.

But you’ll notice that the second action we’re listening for doesn’t reference a class function, but uses a closure instead.  Why?  Personal preference really.  I didn’t see the point in creating a whole new function just for one line of code.  Keeping it in a closure doesn’t affect the functionality, and keeps the class tidy and easy to understand.  In this case, all we’re saying is that when the WP admin screen initialises we want to make sure there is a setting available for our options page to use.  Again, that will become clear later.

So, let’s look at the first action we set up, which listens for the admin_menu  action.  This allows us to add a menu item to the WordPress sidebar.  The function looks something like this:

You’ll need to refer to the documentation for add_management_page()  to see the full range of options available, but in this case we’re adding a menu item to the sidebar (as a subitem of ‘Tools’) that will be called “MD Things”, which will only be visible if the logged in user has permissions to manage_options  (so usually an Administrator).  It’s only one line, so why not put it in a closure like the other action?  Notice the last argument – we’re referring to $this , which wouldn’t work in the context of a closure.  That last bit is important, because that references another function in our class that actually displays the options page:

First of all it checks that we actually have permission to view the options page, and chucks us out if we haven’t.  It’s an unlikely scenario to have to cater for, but best to be safe.  Then we tell WordPress that our plugin uses an option variable, using get_option() .  And, finally, we show the options page itself.  This approach is my personal preference, and don’t feel you have to include the ‘.tpl’ bit in the filename if you prefer a different convention.  Here’s what options.tpl.php  looks like:

There are some styling conventions in WordPress, although I’ve found they’re not particularly well documented, so the best thing I can recommend is to look at the HTML of an existing plugin options page and replicate it.

But functionally, that’s it.  When you hit the submit button WordPress will automatically handle the form submission and save your data in the setting for this plugin.  You don’t need to worry about database access or parsing or anything… WordPress just works.

Something else that saves our bacon is that we’re saving all our settings as an array of values.  We register one option for the plugin via register_setting() , and we store all our settings as an array within that option, for example in the input above name="md_things_plugin[mythings]" .  The beauty of this is that if our plugin needed more settings, we simply add another element to the array, rather than having to create more options with register_setting() .  Nice and tidy.

Step 5: Asking for visitor input

We’re going to need a shortcode to display a form.  Again, the WordPress documentation would have you believe that this is done procedurally, but it doesn’t have to be.  I like to separate my functionality from my display, so I use template files to keep things tidy.

I’m using a closure again, because it’s tidy, but you could use a class function if you prefer.  All I’m doing here is including the template file, which looks something like this:

Now if we put that [md_things_form]  shortcode on a WordPress page or post somewhere, it will show our form.  When the form is submitted, it will be sent to WordPress’s internal admin-post.php  file, which we can hook into to process the form ourselves.  Here’s how we do that, again adding to the __construct()  function:

admin_post_  listens for post data sent to the admin-post.php  file, nopriv_  listens only to post requests that come through from someone who is not logged in, and md_things_visitor  is the identified we passed from the form submit button.  We can then route the request to a class function:

This inserts a new row in our database table, storing the value the visitor entered into the form.  I’m using intval()  to validate the input, but you might want to use something else depending on the format you expect.  Then it redirects back to the page we came from, as specified in the other input in the form (if anyone knows of a better way of doing this, let me know!).

As an added bonus, we can make that form template include a bit more information.  For instance, this bit of code would show the value our administrator put into the WordPress options page:

We can also create a static function in our class and reference it directly from the template:


Hopefully that’s given you enough to get started writing your own object oriented WordPress plugin.  If I’ve missed anything, or if you’ve spotted any mistakes, let me know in the comments below!

Making my blog more personal

Successful bloggers, and indeed writers in most fields, will tell you that the key to success is to pick your target market and stick to it.  No surprise, then, that the most read blogs are ones where their authors talk religiously about their chosen topic, whether that be a blog about programming methods or a blog about one man’s journey to become a vintage bus driver.

In spite of this well-acknowledged fact, you’ll notice that my blog is still littered with a whole plethora of categories, covering all sorts of topics and areas of life.  I have chosen not to focus on one target audience, but to write infrequently about everything instead.

Now, finally, I’ve got round to introducing a way for you, the reader, to take control of my blog and only show the articles you’re actually interested in.

A few changes

A while back my blog decided, in its infinite wisdom, that allowing access to the control panel was in fact not what I wanted to do, despite my many attempts to do so.  I would go to the login page, enter my details, hit the ‘go’ button, and be instantly redirected back to the login screen.  Helpful.  I did some digging around, and it appeared that as far as WordPress was concerned I was actually logged in, it just wouldn’t show me the control panel itself.  That meant I couldn’t approve or reject comments, I couldn’t add new posts, I couldn’t update the templates, I couldn’t add or remove any plugins, and I couldn’t spend time tinkering with my blog.  Maybe it thought it was doing me a favour.

In any case, it’s taken me until last night to resolve the matter.  I had previously tried copying new files across to upgrade to the latest version, but that didn’t work.  So last night I took a full backup of everything, deleted all the core files from the server, and uploaded a fresh load of files.  And as if by some deep and powerful magic, my command over my online presence was finally restored.  With that liberation still fresh, I jumped on the opportunity to make a few changes.

The most obvious change you’ll see is that I’m now importing my Twitter feed.  When I post a new tweet, it’ll get displayed here on my blog too, appearing like a little speech bubble.  This is actually a category in WordPress too, so I can non-Twitter mini-posts too.  Like for those times when I really feel the need to say something to the world, but Twitter doesn’t give me enough characters, and a full-on multi-paragraph post isn’t necessary.  Of course, I understand that you may not want my Twittering to come up in your RSS reader, so if you want to continue reading my blog by RSS but excluding these micro-posts you can now use this new RSS feed URL:

Other changes I’m bringing in include a mobile-enabled view of my blog, so that you can read my posts from your phone.  I’ll hopefully also figure out a way of updating my blog from my mobile too, so that I can blog on the move.

I shall also be adding a new ‘Family’ category, as I seem to be writing an increasing amount about our son Samuel, and it feels appropriate to recognise his significance with his own category.

EDIT: If you’re seeing the Twitter micro-posts but they’re unformatted (i.e. not in funky speech bubbles) you probably need to refresh your browser to reload the stylesheet.  To refresh your browser, click the refresh button in the toolbar.  Or press F5.  Or press CTRL-R.  Or CMD-R if you’re on a Mac.  Or ALT-CTRL-SHIFT-TAB-R-X-N-SPACE if you happen to have that set up as a custom keyboard shortcut.

The Competition

I remember when I first started blogging.  My friend Phill was responsible for starting me off, back when we were at uni together.  He had a blog, and said that I should have one too.  So I registered a free domain name – – and pointed that at some free webspace that came with my Dad’s dial-up internet connection (with permission… I think), and wrote my first blog.  If memory serves, it said something along the lines of ‘hey, I’ve got a blog, not sure what to write here, but we’ll see how it goes’.  Once the bug had bitten, there was no stopping me.

That first blog was a straight HTML page.  I edited the HTML, probably in Notepad, put the latest post at the top of the page, and re-uploaded the file.  Simple but effective.  But over time it became a little unwieldy.  So Phill got me to beta-test his PHP-MySQL blogging system that he’d been tinkering with, and that opened up a lot more options.  Before long though I felt it necessary to migrate to something more substantial, made the move to WordPress (importing my old blog posts), and have been a blogging sensation ever since.  Well, maybe not the sensation bit.

But now, an ominous cloud hangs on the horizon.  A tiny ripple out at sea that has the potential to grow into a tidal wave that will rip through all that once was safe and secure.  My wife has a blog.

New blog design

screenshotJust a quick note to say that my new blog design is finally live and kicking, with just a few technical bugs to sort out, most notably that comments aren’t working at the moment.  I’m trying to find a solution to that one, and then everything should be fine.  I also realise that the three latest comments have also been lost; I am aware of that, it’s because I’ve moved this site to a new server.  Hopefully I’ll figure out a way to reinstate those comments too.  So, sorry for the inconvenience of not being able to litter my blog with your own thoughts, but I’m working to resolve that!

In the meantime, please do enjoy the new look for the blog, in particular the header image which changes depending on the time of day, and time of year, so check back at different times during the day to see different images.  I’m also quite pleased with the comments post-it notes too, which work quite well.  The only caveat with that is that I have had to put a cap on the length of comments, otherwise it all started to look silly.

Once comments are up and running again, please feel free to let me know what you think.  In the meantime, twiddle your fingers, or if you really do want to tell me something send me a postcard, or a homing pigeon, or smoke signals, or something.

Blog update

Just quick note to say that I have updated my blog template to the new design I’ve been working on.  It’s not quite finished yet, and there are some links that won’t work yet, but I’m out this evening so those things will have to be added tomorrow.  The basic functionality is there though, and I’m much happier with this design than I was with the previous off-the-shelf one I tried a while back…

Anyway, once it’s all settled in, feel free to let me know what you think of it.

Missing media buttons in WP 2.5 – partial fix!

I’ve been hovering on the WordPress forums recently, keeping my eyes peeled for a solution to my missing media buttons following up my upgrade to WordPress 2.5 a week or so ago. Today, prompted by a post by jeenie involving looking at the source code, I had a poke around and managed to get half way there. As you can see from the attached screenshot (which proves it all works!!), I can now access the functionality, even though the images still don’t show. It’s a curious thing, given that it looks like a fairly simple bit of code that oughtn’t to have any problems at all.