WordPress Plugin Structure

The power of WordPress lies in its pluggable infrastructure.  Unlike other content management applications which require you to edit the core code of the system to make changes, WordPress supports plugins.  These smaller applications tie in to a rich API provided by WordPress that allows you to change just about everything about the application and customize it as needed.

The official plugin repository on WordPress.org is currently home to over 20,000 distinct plugins.  Each one adds some new functionality to WordPress, giving you the ability to tweak content, change colors, adjust layouts, or integrate with external systems.  This doesn’t even begin to cover the hundreds of premium plugins you can find online that provide even richer functionality.

Most WordPress developers will, at some point, be asked to create some kind of plugin for a client site. These client plugins can range from a shortcode manager to some kind of advertisement rotation engine to an API integration with a third-party customer management system. Instead of focusing on the what for your plugins, this tutorial will focus on the how. Namely, the three different ways you can structure a WordPress Plugin.

Functional

The quickest, easiest approach is to use standard functions to define your custom functionality. For simple plugins, this is actually the best and most straight-forward approach.

All of your plugin code will reside in a single file – my-plugin.php – in the root of your /my-plugin directory. Prefixing every function name with a unique string (i.e. myplugin_) will prevent your code from colliding with any code shipped by another developer. It also makes it easy for other developers to remove and re-add action hooks and filters should they need to.

The following example code will add the number of draft posts to the Right Now box on the WordPress dashboard:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function myplugin_count_posts() {
  $posts = wp_count_posts();

  $num = number_format_i18n( $posts->draft );
  $text = _n( 'Draft', 'Drafts', intval( $posts->draft ), 'myplugin_translate' );

  if (  current_user_can( 'edit_posts' ) ) {
    $num = "<a href='edit.php'>$num</a>";
    $text = "<a href='edit.php'>$text</a>";
  }

  echo '<tr><td class="first b b">' . $num . '</td>';
  echo '<td class="t">' . $text . '</td></tr>';
}
add_action( 'right_now_content_table_end', 'myplugin_count_posts' );

This hook can easily be removed, reordered, or otherwise manipulated by other developers if they know the hook name. Keep things consistent in your code, and things will work well for community involvement.

Unfortunately, if your plugin is much more complex, the functional approach can quickly become a nightmare. Figuring out which functions are defined where in a large, monolithic file can be challenging. Once you start breaking your one file into smaller pieces of distinct functionality, though, you face other organizational difficulties.

For more complex plugins, you should begin structuring things in a class format.

Static Class

Just like prefixing function names can prevent function collision, making your functions all static members of a class will, essentially, “namespace” your plugin’s functionality. After prefixing, this is the easiest way to organize your plugin in such a way that it plays well with other systems in the WordPress infrastructure.

The trick is that action hooks and filters are now added using an array notation rather than a straight string. For example, instead of add_action( 'wp_head', 'myplugin_head' ), you would call add_action( 'wp_head', array( 'My_Plugin', 'head' ) ). Similar notation, but it’s important to include the class reference here, otherwise WordPress won’t know where your code is defined.

Breaking your function up into several files is best done when each file represents a distinct class. It’s easy to know which functionality is encapsulated within which class if you keep related functions together and are clear with your project names. It’s also relatively easy for other developers to manipulate your code later, so long as they also remember the static class notation you used with add_action().

Here is our functional example from above, but rewritten as a call from a static class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class My_Plugin {
  static function count_posts() {
    $posts = wp_count_posts();

    $num = number_format_i18n( $posts->draft );
    $text = _n( 'Draft', 'Drafts', intval( $posts->draft ), 'myplugin_translate' );

    if (  current_user_can( 'edit_posts' ) ) {
      $num = "<a href='edit.php'>$num</a>";
      $text = "<a href='edit.php'>$text</a>";
    }

    echo '<tr><td class="first b b">' . $num . '</td>';
    echo '<td class="t">' . $text . '</td></tr>';
  }
}
add_action( 'right_now_content_table_end', array( 'My_Plugin', 'count_posts' ) );

Some tutorials recommend an instantiated class with some static elements for adding/removing action hooks and filters. Their code will work, but is a bit hacky. Particularly if you’re ever in a place where the class can be instantiated more than once. With that in mind, I would never recommend that approach – either keep everything static, or go with my favorite pattern below.

Singleton

A singleton is a class that can only be instantiated once. Every other reference to the instantiated object is a reference to the same object. This is a pattern that works beautifully for plugins because, honestly, you only ever need to instantiate the plugin once. It’s also the way I prefer to build plugins since it keeps things clean, avails private variables to the plugin, and is an easy pattern to follow.

Basically, a singleton is a class with a read-only static instance and a private constructor. When you attempt to get the class instance, it checks to see if the class has been instantiated – if not, it fires the constructor internally and stores the constructed object inside the static instance. Now, every request for the instance returns the same object. Here’s a very basic example of a singleton class.

1
2
3
4
5
6
7
8
9
10
11
12
class Singleton {
  private static $instance = false;

  public static function get_instance() {
    if ( ! self::$instance ) {
      self::$instance = new self();
    }
    return self::$instance;
  }

  private function __construct() { }
}

With a singleton class, you can have methods and members that are members of the class, can refer to each other, and can reference data (properties) which are private to the class itself. For example, if you build a singleton and populate it with certain properties that are meant to be read-only, you can store those values as private members of the class and expose public getter functions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class My_Class {
  private $hidden_var; // Invisible outside of the class
  var $visible_var; // Visible outside the class

  public function get_hidden() {
    return $this->hidden_var;
  }

  public function __construct() {
    $this->hidden_var = 4;
    $this->visible_var = 6;
  }
}

$instance = new My_Class;
echo $instance->visible_var;  // Echos 6
echo $instance->hidden_var;   // Fatal Error
echo $instance->get_hidden(); // Echos 4

$instance->visible_var = 2;   // Works
$instance->hidden_var = 2;    // Fatal Error

Removing action hooks and filters is straight forward because you always have access to the instance of the class that wired them up in the first place. This means it’s easy for developers down the road to manipulate your code.

Here’s the same plugin example from above, but rewritten as part of a singleton class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class My_Plugin {
  private static $instance = false;

  public static function get_instance() {
    if ( ! self::$instance ) {
      self::$instance = new self();
    }
    return self::$instance;
  }

  private function __construct() {
    add_action( 'right_now_content_table_end', array( $this, 'count_posts' ) );
  }

  public function count_posts() {
    $posts = wp_count_posts();

    $num = number_format_i18n( $posts->draft );
    $text = _n( 'Draft', 'Drafts', intval( $posts->draft ), 'myplugin_translate' );

    if (  current_user_can( 'edit_posts' ) ) {
      $num = "<a href='edit.php'>$num</a>";
      $text = "<a href='edit.php'>$text</a>";
    }

    echo '<tr><td class="first b b">' . $num . '</td>';
    echo '<td class="t">' . $text . '</td></tr>';
  }
}

$my_plugin = My_Plugin::get_instance();

Conclusion

Most developers are just beginning to embrace object-oriented design patterns with WordPress. Unfortunately, few of us have enough experience with OOP to discern good versus bad programming patterns. Many developers are using instantiated objects to encapsulate plugin functionality – and running the risk of multiple instances being created during a single request. Others are properly using static classes and objects, then running afoul of global variables when attempting to pass data from one static method to another.

The most efficient pattern for WordPress plugin development is, hands down, the singleton. It can only be instantiated once, and has the ability to store data internally for quick recall – meaning member functions can easily pass data back and forth without cluttering the global namespace.

Which patterns are you using for plugin development? What other alternatives have you found?

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. I think is better, that you include the class not via

    1
    $my_plugin = My_Plugin::get_instance();

    in WordPress. Use the hook for plugins and the stacktrace is fine

    1
    add_action( 'plugins_loaded', array( 'My_Plugin', 'get_instance' ) );

    best regards

    • In some of my work, I actually throw a reference to the instance into a global variable, which is why I went with the declarative part. But if you’re avoiding globals (which you should be) your action hook would be a much better way to go about it. +1

  2. About your try to echo parts of the singleton: If you want to echo something from a class, you should simply use the __toString() magical method. See the “Dynamic Image Resize”-Plugin I wrote for an example: https://github.com/franz-josef-kaiser/Dynamic-Image-Resize/blob/master/dynamic_img_resize.php#L60

    • Yes, I could have used __toString(). But that wasn’t really the point of my code example here.

      • Thanks for fixing those code parts. I guess you’ll have to do it again with this comment :)

        About the example: I understand you and what you were trying to show. But to complete what I tried to tell: Magical methods are there for a reason. If you want to echo the result, use __toString(), if you want to get the value of a private var, use __get() (instead of get_hidden()), etc.

        To target the init process of a plugins bootstrap file (or just a single file singleton), I use pretty much the same setup as Frank mentioned, as you can see at this plugins code: https://github.com/franz-josef-kaiser/current-admin-info/blob/master/bootstrap.class.php .I hardly believe that the main method of a plugin should be hooked there. The hook is well known and there for a reason. From thereon every dev can hook in wherever (s)he needs from inside the __construct() method.

        • Yes, but since not everyone uses (or is even aware of) PHP’s magic methods or how they work, I chose to skip them so as not to clutter the conversation. The article is about class structures in plugins; PHP magic methods can be addressed elsewhere. Including them in a blog post targeted at beginning developers would just add confusion for now, which is why I didn’t bring them up.

  3. sunsetsystems says:

    Hi Eric, could you explain what this statement means? I’m trying to understand why a singleton is better than making everything static. Thanks.

    “Others are properly using static classes and objects, then running afoul of global variables when attempting to pass data from one static method to another.”

    • Actually, using a true namespace is better than making everything static.

      My point in the quote, however, is that static variables within a static class are akin to global variables in a non-namespaced application.

Trackbacks

  1. [...] I published this post it turns out Eric Mann had been thinking along similar lines and published WordPress Plugin Structure. Eric then followed up both our posts with The Case for Singletons for which he got some IMO [...]

  2. [...] has even written three (3) recent posts advocating (lazy-initialized) Singletons for use in WordPress [...]

  3. […] Functions and Classes and Singletons, Oh My!. October 15, 2013 Folded neatly in: PHP OOP Another project from Waterstreetgm. Happily powered by WordPress Template file:/home/waterstr/public_html/bookmarkie/wp-content/themes/treasureisland/index.php […]

Leave a Reply