Classy Plugins

I was asked a few weeks ago why I structured my WordPress plugins the way I do.

Anyone who has spent any time looking at my code knows that I like to keep my main functions in a class and wire up action hooks and filters in the root of the plugin.  But few people have asked me why I set things up this way.

My explanation is in two parts:

  1. Writing clean code
  2. Writing easy-to-maintain code

Though it should be noted now that, while this particular development style makes heavy use of classes within PHP, this is not object-oriented programming.

Let me say again – this is not object-oriented programming.  I use classes often to define custom objects, but in this situation I use them merely as convenient wrappers for code.

Writing Clean Code

Ideally, code should be self-documenting.

Function names should be concise yet descriptive.  Variable names should reflect what’s contained within them.  I should be able to tell from glancing at your code what it does without looking to external documentation.

Where code isn’t enough to explain what’s happening, a quick in-line comment usually is.

To stick to this idea, I like to name my plugin functions after the WordPress hooks they tie to.  If I want to hook onto the init hook, I’d like to do so with a function named init().

And that’s a problem because that function name is already used.

To keep things clean, I make all of my plugin functions public, static members of a class.  Then, I can specify the class name when hooking in to WordPress and can keep things clean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class My_Plugin {
  public static function init() {
    add_image_size( 'mp-image', 120, 140, true );
  }

  public static function query_vars( $public_vars ) {
    $public_vars[] = 'mp-paged';
    return $public_vars;
  }

  public static function the_content( $content ) {
    global $post;
    if( 'mp_post_type' != $post->post_type )
      return $content;

    $mp_post = new MP_Post( $post );
    return $mp_post->summary;
  }
}

A lot of other developers prefix their function names.  I have no problem with this as an alternative practice.  I just have my own preferences for code organization.

Easy-to-maintain Code

I keep all of my hooks in one place so I don’t need to hunt for them later.

My first experience with an “advanced theme framework” was what should have been a 2-hour design project.  Instead I spent 2 weeks hunting through the code and referencing online documentation to find out which hooks were defined in which files so I could override them.

It was painful.

As much as I like the elegance of seeing a fire_main_engines() or similar method in a plugin root (leaving that function to call others that wire up the hooks), that kind of model is difficult to maintain.  If all of the hooks are instead defined in one spot, it’s easy to add new ones, remove deprecated ones, or just see at a glance every part of the plugin that interacts with WordPress.

1
2
3
4
5
6
require_once( 'lib/class.my-plugin.php' );

add_action( 'init',        array( 'My_Plugin', 'init' ) );

add_filter( 'query_vars',  array( 'My_Plugin', 'query_vars' ) );
add_filter( 'the_content', array( 'My_Plugin', 'the_content' ) );

What We Gain

The folder structures of my plugins are very uniform and easy to follow. The root directory contains a single PHP file with plugin information, licensing, and all of the hooks used by the system. There’s also a readme file containing a changelog, FAQs, and other useful information. If the plugin adds presentation elements, there are a few screenshots.

The /lib folder contains PHP files with static classes that wrap the functionality of the plugin. They are either require()ed or include()ed by the root PHP file.

You can browse the base file in the root directory to see where my plugin ties in to WordPress. Based on the function and class name in the hook, you know exactly which file to look at for the actual functionality.

Is this the best way to do things? I don’t know for sure. All I do know is that it’s clean and efficient.

About Eric

Eric Mann is a writer, web developer, and outdoorsman living in the Pacific Northwest. If he's not working with new technologies in web development, you can probably find him out running, climbing, or hiking with his dog.

Comments

  1. Glad to see people using this technique. It avoids the stupid “xyz_mycode” function prefixes, and simply makes your code look cleaner and less hacked together.

    One slight difference in how I do it is that I put all the add_action/add_filter code inside a static “start” method, and call that from outside the class. That way I can reference the class name with the __CLASS__ magic constant, rather than hardcoding it in a string. The advantage is that I don’t have to do any string find/replacing if I ever rename the class (PHPStorm is smart enough to replace real class references, but not references inside strings).

    • Using __CLASS__ would make things a bit easier in that regard. However, I like to copy-paste my code a bunch and keeping static strings forces me to go back in and make sure the calls are all correct. More of a reminder for me to not be lazy than anything else.

  2. “My first experience with an “advanced theme framework” was what should have been a 2-hour design project. Instead I spent 2 weeks hunting through the code and referencing online documentation to find out which hooks were defined in which files so I could override them.”

    Hahahaha … I am now sitting here at 02:27 am reading your interesting posts rather that being up ‘another’ full night hunting through the code of a so called ‘professional application framework’-based theme as MOST of them I’ll have to override if I want to plug into this so-called ‘API’. I shudder at what people call APIs :P

Leave a Reply