Blurbette Plugin: An Object-Oriented Project

Download the Blurbette Plugin


In this series I’ll take a comprehensive look at creating a plugin from scratch. The concept is to create a custom post type called a Blurbette, which can be inserted into any posts, pages or widgets, and to offer a number of management utilities to create and control. You can download the source using the above link, and use it to follow along.

This series assumes you’re (at least a little bit) familiar with PHP objects and classes. I’ll show you how to design and organize your classes for WordPress compatibility, and acquaint you with some of the benefits of PHP’s object-oriented coding. I’ll call it OOP (Object-Oriented Programming), even though purists will whine because it’s not “true” object structure, or for that matter, programming.

You’re the right audience for this series if you’re reasonably familiar with PHP and WordPress coding, but haven’t explored organizing projects this way. If you’re not familiar with PHP objects and classes, read a good primer such as PHP’s own documentation. Fortunately, the overall concepts are quick and easy to learn; I’ll be discussing some of the finer points in these chapters.

Procedural Coding

Much of the WordPress coding info you’ll find out there — indeed, even the snippets on this website — direct you to create some functions, and hook those functions into actions or filters. You must be sure those functions have unique names that are unlikely to clash with functions in WordPress plugins, core, or theme files…

add_action('init','WPCX_MyFunction_ThatDoes_Something');
function WPCX_MyFunction_ThatDoes_Something() {
// … and so on …
}

These functions must be placed in a theme’s functions.php file, or strung together inside a plugin file.

You can (and many do) create whole themes or plugins this way; it’s known as “procedural coding.” It’s like sticking pins in a tree, and doing your best to keep those pins organized.

What happens when your functions begin to number in the dozens, or even hundreds?

You might organize your functions in separate files and use require_once statements to include them all. But as the complexity grows, so does the difficulty in finding the appropriate functions when it comes time to debug. What about that ajax function that’s called from the admin, and also by a shortcode? Is that in your “ajax.php” file, your “shortcodes.php” file, or your “admin.php” file?

Object-Oriented Coding

In addition to many benefits, OOP provides an inherent way to keep your work organized. Where procedural coding is throwing a bunch of marbles into one big bucket, OOP is several buckets with cleaner marbles in each.

Instead of having to invent complex names for each function that are unlikely to clash:

function wpcx_image_metabox_nonce() { …

… you can name your “bucket” with a unique identifier,* and use a clean, plain method name:

class WPCX_Image_Metabox {
	function nonce() { …

More than merely cleaning up the code, OOP causes you to approach your project in an organized way. Each of your project’s components can be a separate class, and all related methods and properties can be contained within it.

In your analysis and design phase, you’ll think in terms of separate entities — tools, panels, utilities, and so on — rather than points along a single timeline. Some entities may be similar, so you’ll engineer a common prototype from which they can be spawned.

Furthermore, by their very nature, classes can be separated modularly — so different members of your team can work on each class individually. As a bonus, classes often turn out to be repurposable and easy to implement in future projects.

*PHP 5.3 has introduced namespaces, which provide even cleaner naming methods. If you’re sure your code will only run on servers with PHP 5.3+, this is an excellent feature to implement in your code.

Some Things to Remember

  • Static vs. Instantiated: Classes’ methods and properties can be defined static, which mostly means they aren’t intended to store unique data in separate instances. These are referenced using the class name, and not the name of the object instantiated from it:
    class MyClass {
    	public static function StaticMethod() {
    		echo 'Say Cheese!', PHP_EOL;
    	}
    }
    

    … you would call the static function StaticMethod() like this:

    MyClass::StaticMethod();
    

    In contrast, methods and properties can be “non-static” (the default declaration), which means you intend to instantiate an object from the class before referencing them:

    class MyClass {
    	public function NonStaticMethod() {
    		echo 'Watch the Birdie!', PHP_EOL;
    	}
    }
    

    … you would call the “non-static” method NonStaticMethod() like this:

    $some_object = new MyClass;
    $some_object->NonStaticMethod();
    

    When organizing your project, you’ll plan to declare some methods/properties static, and others non-static. One good practice is to group many static members into designated “static classes” (in quotes because PHP makes no such distinction). If you’re conceiving classes with lots of mixed static and non-static members, there’s a good chance you could engineer a clearer concept.

  • Hook Reference You may or may not be aware, but there are several ways to reference method names within WordPress hook callbacks. Each defines a simple array — the second element is always the (quoted) name of the method; the first element varies depending on certain circumstances:
    1. Static, from outside the class:
      add_action( 'init', array('MyClass','StaticMethod') );
      
    2. Static, from within a method in the same class:
      public static function HookInitStatic() {
      	add_action( 'init', array(__CLASS__,'StaticMethod') );
      

      (__CLASS__ simply outputs the class name; you could also quote the class name here as in the previous example.)

    3. Non-static, from outside the object:
      $some_object = new MyClass;
      add_action( 'init', array($some_object,'NonStaticMethod') );
      
    4. Non-static, from within the class:
      add_action( 'init', array($this,'NonStaticMethod') );
      
  • Public methods: Action and filter callback methods must be declared public (not private or protected).
    add_action( 'init', array('MyClass','StaticMethod') );
    class MyClass {
    	public static function StaticMethod() { 
    …