Many tutorials that explain how to write a WordPress plugin (including ours) show the use of global functions for implementing action and filter hooks. In our case we used global functions so we had less to explain. But now that we've gotten past that first tutorial we think once you understand using classes you'll find no reason to use global functions for filter and action hooks ever again.

Converting from Global Functions to Classes

Revisiting our Basic WordPress Plugin example we have:

  1. <?php
  2. /*
  3.  * Plugin Name: Thanks for Reading
  4.  */
  5. add_filter( 'the_content', 'tfr_the_content' );
  6.  
  7. function tfr_the_content( $content ) {
  8.   return $content . '<p>Thanks for Reading!</p>';
  9. }
<?php
/*
 * Plugin Name: Thanks for Reading
 */
add_filter( 'the_content', 'tfr_the_content' );

function tfr_the_content( $content ) {
  return $content . '<p>Thanks for Reading!</p>';
}

We can easily modify that plugin so it instead uses a class as a code wrapper:

  1. <?php
  2. /*
  3.  * Plugin Name: Thanks for Reading
  4.  */
  5. class Thanks_For_Reading_Plugin {
  6.   function __construct() {
  7.     add_filter( 'the_content', array( $this, 'the_content' ) );
  8.   }
  9.   function the_content( $content ) {
  10.     return $content . '<p>Thanks for Reading!</p>';
  11.   }
  12. }
  13. new Thanks_For_Reading_Plugin();
<?php
/*
 * Plugin Name: Thanks for Reading
 */
class Thanks_For_Reading_Plugin {
  function __construct() {
    add_filter( 'the_content', array( $this, 'the_content' ) );
  }
  function the_content( $content ) {
    return $content . '<p>Thanks for Reading!</p>';
  }
}
new Thanks_For_Reading_Plugin();

Naming Conventions

Note we changed the name of the function back to the simpler named the_content() because now we can. And we named our class Thanks_For_Reading_Plugin because it's concise, it clearly identifies the plugin, and its highly unlikely to conflict with any other plugin. And we can't say the same for our 'tfr_' prefixed function.

Note that for classes using in WordPress plugins and themes we recommend following the WordPress Coding Standards; Capitalized_Words_Separated_By_Underscores.

Leveraging Features of PHP Classes

The other aspects to discuss are:

  1. So what's a "method?!?"
  2. The PHP object constructor named __construct(),
  3. The singleton object instantiation using the PHP new operator,
  4. The array() wrapper around the method name with $this as first element, and

What is a "Method?"

"Methods" are functions that are specific to classes. Many programming languages implemented object orientation before PHP and collectively they established the "method" terminology. When PHP implemented classes they chose to use the syntax function instead likely because PHP developers were already familiar with the term function.

So it's quite simple really: Methods are functions that are specific to an object or class. If it's a function defined within a class it's called a "method." If it's defined outside of a class it's called a "function."

Did you need to know this? Not really, but it might help you clear up confusion now or in the future.

Use new to Trigger the PHP Object Constructor

The function named __construct() is a special function in PHP designed to automatically run whenever a new object of a class is created. The following code creates a new object and our main purpose for creating the instance is so that the __construct() will be called:

  1. new Thanks_For_Reading_Plugin();
new Thanks_For_Reading_Plugin();

You don't need to assign the newly created instance to a variable as the code in the constructor that called add_filter() will do that indirectly.

Inside that __construct() method we only need to add a filter hook for 'the_content':

  1. function __construct() {
  2.   add_filter( 'the_content', array( $this, 'the_content' ) );
  3. }
function __construct() {
  add_filter( 'the_content', array( $this, 'the_content' ) );
}

Using $this with add_filter()

In our basic plugin example we just passed the function name 'tfr_the_content' to our add_filter() call but now that we are using a class we need to specify which object instance will provide the context for our classes' function a.k.a. it's method. The special variable $this acts as the current instance of the class for any code within the class. And when PHP needs a "callable" it can accept a two-element array with the class instance in the first element and the name of the hook in the second element.

  1. add_filter( 'the_content', array( $this, 'the_content' ) );
add_filter( 'the_content', array( $this, 'the_content' ) );

And that's really all there is to it.

Summary

Switching between function syntax and and class as code-wrapper syntax is effectively trivial yet it allows cleaner code and the ability to protect the names of your functions from conflicting with those of written by another plugin or theme developer. And even if you don't follow understand it all yet, just copy and paste the example and before you know it you'll be surprise that it every seemed confusing.

So now you know, and there's no turning back. :)

Follow up Posts

If you'd like to learn more about writing class-based WordPress plugins you might be interested in this post too:

Update

Since 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 unreasonable heat from posters on Hacker News.

I'll start by saying I think of Eric as a good friend and I always have great respect for his work. In general I agree with almost everything he wrote although I don't prefer his exact syntax approach to singletons. He uses a "lazy initialization" approach and I advocate for a "eager initialization" approach as the terms are defined on Wikipedia, at least for WordPress plugins. I'll be writing more about Singletons here at HardcoreWP in the near future.

26 thoughts on “Using Classes as Code Wrappers for WordPress Plugins

    • Hi @Castle,

      Thanks for the comment. Here’s the thing, using classes for WordPress plugin code-wrappers doesn’t really have anything to do with OOP. Don’t let a fear of OOP concepts scare you aware from classes, they work great without you knowing the first thing about OOP.

      In this post we are only using classes to control the namespace for the methods in our class. Note I use the term “namespace” here conveniently; I’m not referring to built-in namespaces in PHP 5.3 that few people building WordPress plugins use since WordPress still supports users on PHP 5.2.4. By putting functions in classes instead of putting them in the global namespace with global functions you can use shorter and simpler function/method names. Instead of having to call your filter function for the 'the_content' hook my_plugin_name_the_content() you can name your plugin My Plugin Name and then name your method just the_content(). See how simple that is?

      Funny thing I’ve already written an editorial about why using classes for code-wrappers is not OOP but I decided not to publish it yet because I want to focus on publishing some really great tutorials and code techniques before I start getting opinionated on this blog, cause those who know me know I do have strong opinions! :)

      And yes, we plan a lot more of these kind of tutorials although we plan to ramp up to advanced topics pretty soon. I say “we” because we plan to have others from NewClarity team blog here soon too.

      -Mike

      Reply
      • Hi Mike.

        Yeah.. you spot on! The fear of OOP theory sent me away from classes.
        I hope to see your ‘unpublished’ article very soon :-)

        Cheers!

        Reply
  1. Hi Mike,

    Sorry to bother you again, but I read the article over and over and so far I couldn’t figure out why you need to use the __construct () function. All the __construct part is not clear. Can you just add add_filter( 'the_content', array( $this, 'the_content' ) ); right after you declare the class name?

    Reply
    • Castle, the __construct() function in a class is automatically called when you create an instance of the class by calling new Thanks_For_Reading_Plugin(). Since it’s going to be called anyway, putting your hooks and filters there works well.

      Also, you only have access to $this from inside the class – it’s the way the class can reference itself. So any code that references $this (like adding a filter) needs to be inside the class. And the code that adds filters and actions has to be inside a function in the class – so the constructor is the perfect place for it.

      Reply
  2. Hi Mike,
    at first, nice that I can read now posts from you on your blog!

    I think it is not a fine way to inlcude a class in wp with new CLASS_NAME; not realy under control from WP. WP have hooks for include, like plugins_loaded for plugins. Maybe see this example, mirror from your class on this post, but changed in include via hook and add filter for output content.

    < ?php
    /*
     * Plugin Name: Thanks for Reading
     */
     
    add_action( 'plugins_loaded', array( 'Thanks_For_Reading_Plugin', 'get_instance' ) );
    
    class Thanks_For_Reading_Plugin {
      protected static $instance = NULL;
    
      /**
       * Handler for the action 'init'. Instantiates this class.
       *
       * @since   0.0.1
       * @access  public
       * @return  $classobj
       */
      public static function get_instance() {
        NULL === self::$instance and self::$instance = new self();
        return self::$instance;
      }
      
      public function __construct() {   
        add_filter( 'the_content', array( $this, 'the_content' ) );
      }
      
      public function the_content( $content ) {    
        return $content . apply_filters( 'the_content', 'Thanks for Reading!' );
      }
      
    }
    

    Reply
    • Hi @Frank,

      Thanks much for commenting.

      I see that your approach is similar to the approach Eric Mann advocates and I saw your comment other there too. You are suggesting lazy Initialization as was Eric, but I’m not sure I see it as more than a coding style preference.

      Are you advocating this approach so another plugin could stop the loading of the class or priority to run it’s own code prior to loading the class? I guess I can see that as a benefit although I’ve never actually needed that in real-world usage. Have you come across an example use-case to explain where you needed this? Or is there another reason why you’d got to the extra effort of using the 'plugins_loaded' hook?

      Also, I really don’t like using Class::get_instance() to initialize a plugin class. I’d much prefer eager Initialization using new Class_Name as this post shows.

      So I’d like to hear your justifications on why your approach should be preferred.

      One thing I definitely don’t like about the approach you are advocating is it looks complicated and that initimates people like @Castle above who are not advanced coders like you and me. My plans for this blog are to advocate for simpler techniques to make plugin development more approachable. And yes, some of what I’ve shown so far is complicated but I plan to wrap that complication within easier-to-use helper functions and helper classes.

      For example, what I’d much prefer that could accomplish the same thing your code accomplishes would be a register_plugin( $class_name ) function. The problem is how can we be sure that the code that declares register_plugin() actually loads first? That’s an example of the type of coding issue I plan to cover in future posts here on HardcoreWP.

      Reply
      • I think is more as coding style, is to prevent to set global vars; there is not usefull und necessary.

        I think also, that the hook plugins_loaded the right item to hook custom plugins in the core. This is also the benefit for other developers, that you can filter this hook. You are also shure, that your code include in WordPress not to early, only if WP is ready and will loaded plugins.

        But I think also how you for the posts. The code is easier to understand, but the readers understand the start of loadeing a plugin always on this hook, without understanding of the helper method get_instance – im sure. The register_plugin is a nice idea, but current hte plugins_loaded hook is the onliest way to control the include about a hook or function, same in theme with hook after_setup_theme; like my slides; but current only in german :( maybe later a english version.

        At least: best wishes, happy new year!

        Reply
        • Hi @Frank,

          Thanks for the follow up.

          Note the register_plugin() I proposed would call the 'plugins_loaded' hook so it’s mostly syntactic sugar, not an alternative to using 'plugins_loaded'.

          However as I think about it the techniques we are currently using for client projects actually use 'after_setup_theme' indirectly and these are techniques I plan to ultimately blog about here. It’s not identical to your approach but allows the same flexibility and since I plan to build on prior topics here so that I can ultimately reposition the posts as a series I don’t think it doesn’t make sense to advocate people do things one way and then have them throw away those approaches and replace with something different. Or if it does make sense it would still require me to write a lot more and thus take longer before I can fully present the architecture I plan to blog about.

          To better understand what I just explained here is what the main file of one of our plugins looks like:

          < ?php
          /*
           * Plugin Name: Whatever...
           * Other Info: ...
           */
          
          require( dirname( __FILE__ ) . '/libraries/imperative/imperative.php');
          
          require_library( 'restian', '0.1.0', __FILE__, 'libraries/restian/restian.php' );
          require_library( 'sidecar', '0.1.1', __FILE__, 'libraries/sidecar/sidecar.php' );
          
          register_loader( __FILE__, 'revostock-gallery-loader.php' );

          You can find the three (3) libraries above at NewClarity's GitHub account. The idea is to allow shared libraries and to have plugins that have conflicting libraries to be disallowed at plugin activation time. Then we use 'after_setup_theme' to load the plugin's classes. We have to use 'after_setup_theme' instead of 'plugins_loaded' to ensure all libraries are considered even ones from themes althoughs using libraries in themes is not implemented yet.

          This concept of libraries is actually something I'd very much like to see added to core vs. dependent plugins because I think the use-cases for libraries are not a good match for dependent plugin, and some users really don't like dependent plugins either. I think libraries as a first-class concept could allow for an explosion of innovation for WordPress. They would empower us to collaborate via GitHub on what I would consider to be shared APIs. APIs never become popular as plugins but we all need much of the same functionality so it's crazy for us to be reinventing the wheel all the time. One of the reasons for starting this blog was so I could have a platform beyond Trac to start advocating for additions to core.

          BTW, your comments caused me to review my code and assumptions for our library loader so I updated it quite a bit just now. I hope my explanation makes sense as to why I'd prefer not to promote using 'plugins_loaded' vs. just recommending new Plugin_Class for now.

          And yes, Happy New Year to you as well! I'm looking forward to a lot more discussions like this.

          Reply
          • Hi Mike,

            I think that I understand you points. For me is the difference from plugins and themes also important. For code is it also usefull that you hook about after_setup_theme, but not for style and codex. I understand your meaning for requirements. Often we recreate classes and more, but other plugins have this also inside and it was usefull, that we can reuse this libraries. For me was a solution, that we have functions to register library, like register script and styles and use this via the key, the ID.

            Im afraid for the next posts on this blog, nice topics!

          • Hi @Frank,

            Thanks for your comments. Yes, I’m anxious to write more, but have to finish a client project first!

            -Mike

  3. Pingback: Differences Between WordPress and Web Frameworks

  4. This is hands down the best tutorial on implementing classes within WordPress plugins. It’s the first one I managed to read through without quitting half way through. I won’t go into the merits of which approach is better, but had I seen the code Frank mentioned, I would have probably stopped reading, simply because it’s too much to understand at one go.

    Really looking forward to seeing more great articles like this.

    Reply
  5. Pingback: Tutorials and Resources for Object Oriented WordPress Plugin Development : WPMayor

  6. Pingback: Adding AJAX to your WordPress Plugins – Part 2 | Top Down View

  7. Pingback: Easy Taxonomy Admin Columns with WordPress 3.5

  8. Mike thank you for upgrading my knowledge about classes. I’ve been refactoring my plugin to a class oriented structure now and was wondering how to best make things accessible to other users/devs. Particularly, I was wondering if it is an okay practice to pass $this as a parameter to functions such as apply_filters. Example

    // from within a class
    function render_title(){
    echo apply_filters('my_plugin_block_title', 'Latest comments', $this );
    }
    // a user using filter function outside class
    function my_custom_block_title( $title = '', $obj {
    return $title . ' about ' . $this->celebrity_name;
    }
    add_filter( 'my_plugin_block_title', 'my_custom_block_title' );

    I know it works and it’s so powerful it made me skeptical. I’m not extremely familiar with the potential pitfalls, concerns & drawbacks. Would you consider it a bad practice?

    BTW wish you’d post more, been a long time!

    Reply
    • Hi Peter,

      Absolutely, passing $this is often what core WordPress does and it’s a great way to give your users lots of power.

      OTOH, much power comes with much responsibility; if you publish a plugin with hooks that give direct access to your class instance then you really need to make sure that you class does not change in any backward incompatible manner. And that’s a tall order when the plugin is not really mature.

      So best to balance your options. One rule of thumb I’d consider is to not add many hooks but offer to add them whenever someone comes up with a reasonable need for one; then you have a validated use-case. But be sure to let them know you’ll add hooks for them because they might otherwise not think to ask.

      Or host on GitHub and let them fork it and then they can add the hooks themselves and send you a pull request to see if you approve.

      Anyway, thanks for the kind comments. I’ve been on a great project the past 3 months and I’ve developed lots that I could write about; we’ll see where things head in the near future to see if I have the time. I would like to publish some more of the techniques, that’s for sure.

      -Mike

      Reply
  9. Thank you Mike, very much appreciate your thoughtfulness. I’m carefully considering how exactly I’m going to implement these hooks in my plugin, especially with an eye on keeping them to a minimum as well as user friendly. I found Tim Nowell’s post ‘add_action considered harmful‘ an interesting (and controversial) read. Must admit, it sparked me to apply more discretion when providing hooks in my projects. Maybe that’s an interesting topic for a future post too.

    Reply
    • Glad my comment helped. I had not seem Tom’s post but it was quite the interesting read; thanks for sharing.

      After reading his post I realize I could probably spent a day writing a rebuttal where I agree with him in concept but not in practice for selected use-cases. The primary use-case is for extensibility, and to date no one I’m aware of has presented a better “proper” way to handle extensibility, at least not in PHP 5.3.

      Probably a simpler way so rebut his post is to say “Moderation in all things, especially in programming.”

      Reply
  10. Pingback: Using Classes as Code Wrappers for WordPress Plugins « HardcoreWP | Captain Bookmarks

Leave a reply

required

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code lang=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" extra="">