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:
-
<?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>';
-
}
<?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:
-
<?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();
<?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:
- So what's a "method?!?"
- The PHP object constructor named
__construct()
, - The singleton object instantiation using the PHP
new
operator, - 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:
-
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'
:
-
function __construct() {
-
add_filter( 'the_content', array( $this, 'the_content' ) );
-
}
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.
-
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:
- Enabling Action and Filter Hook Removal from Class-based WordPress Plugins
- Using Singleton Classes for WordPress Plugins
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.
Great stuff!
I was reading http://nacin.com/2010/05/11/in-wordpress-prefix-everything/ and Nanci said that he prefer to use classes too. Since I don’t know OOP, all this things about classes, methods and so no.. is a bit confuse. I would love to see more tutorials like this one with more examples.
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'
hookmy_plugin_name_the_content()
you can name your pluginMy Plugin Name
and then name your method justthe_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
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!
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?Castle, the
__construct()
function in a class is automatically called when you create an instance of the class by callingnew 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.Hi @Castle,
What @Eric Mann said. 🙂 Thanks Eric!
Great. Thanks guys!
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.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 usingnew 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 declaresregister_plugin()
actually loads first? That’s an example of the type of coding issue I plan to cover in future posts here on HardcoreWP.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!
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:
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 recommendingnew Plugin_Class
for now.And yes, Happy New Year to you as well! I'm looking forward to a lot more discussions like this.
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
Pingback: Differences Between WordPress and Web Frameworks
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.
Hi @Jean,
Thanks much! Coming from you it’s especially an honor.
Yes, based on Frank’s comment I have another post planned too.
Pingback: Tutorials and Resources for Object Oriented WordPress Plugin Development : WPMayor
Pingback: Adding AJAX to your WordPress Plugins – Part 2 | Top Down View
Nice tutorial! As an beginner on WP Plugin development, i like the simplicity of how you explain OOP for WP plugin development! Nice work!
Thanks for the kind comments Raymon. Glad my posts are helpful for you.
Pingback: Easy Taxonomy Admin Columns with WordPress 3.5
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!
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
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.
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.”
Pingback: Using Classes as Code Wrappers for WordPress Plugins « HardcoreWP | Captain Bookmarks
Hey
I need to hook to the_content and search for specific div classes sorrounding the content and remove content between thoose divs and then output the content.
For security reasons I cannot just put display:none so I have to really make sure the content goes through my filter and then out to the reader.
I found your article really good and wonder if my thoughts are doable?
Hi Andreas,
Thanks for the compliment.
Yes your idea is almost certainly 100% doable, just a specific use-case for my more general example I used to show how to architect a basic plugin using a class.
Question: How would you intend to identify your
<div>
s? Would they have specificid
s or specificclass
es? Or something else?