Hooks are a fundamental concept for WordPress developers. In previous articles on SitePoint, we’ve learned what hooks are and their importance, the two types of hooks: actions
and filters
with code examples of how they work, and an alternative way of firing actions and filters events and how to hook static and non-static class methods to actions and filters.
In this article, I will cover how to hook methods of an instantiated class (object) to actions and filters, how to integrate a namespaced class method to a hook, caveats of using namespaces in WordPress hook system and solution to them.
Hooking Object Methods
Assume you were tasked by your employer to build an ad manger plugin for a large news website, to make ad insertion to news content seamless. This is how you might go about building it.
You would create an AdManager
class with a number of methods that contain the various ad-networks ad-code.
class AdManager {
/**
* AdSense unit code.
*/
public function adsense() { ?>
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<ins class="adsbygoogle"
style="display:inline-block;width:336px;height:280px"
data-ad-client="ca-pub-xxxxxxxxxxxxxxxx"
data-ad-slot="6762452247"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<?php }
/**
* Buysellads ad code.
*/
public function buysellads() {
// ...
}
}
Say a website theme has an action
called before_post_content
that is fired before the post content is displayed and you want to hook the adsense
method to it to display the ad before any post content. How would you go about it?
You are trying to hook the method to an action outside of the class unlike the examples we’ve seen in part 2 where it was done in the class constructor like so:
public function __construct() {
add_action( 'before_post_content', array( $this, 'adsense' ) );
}
To hook the adsense
method to the before_post_content
action outside of the class (probably in the functions.php
file of the active website theme) in order to display the Google AdSense ads before every post’s content, you will have to replace $this
with an instance of the class.
add_action( 'before_post_content', array( new AdManager(), 'adsense' ) );
And say the class includes a method that returns a singleton instance of the class.
class AdManager {
// ...
/**
* Singleton class instance.
*
* @return AdManager
*/
public static function get_instance() {
static $instance = null;
if ( $instance == null ) {
$instance = new self();
}
return $instance;
}
}
Here is how the adsense
method can be hooked to the before_post_content
action.
add_action( 'before_post_content', array( AdManager::get_instance(), 'adsense' ) );
Namespaces
The WordPress hook system was developed at a time when there was no namespace feature in WordPress. As a result, you might find it difficult to hook a namespaced function and class method to an action
and filter
.
Say your AdManager
class has a namespace of SitePoint\Plugin
as follows.
namespace SitePoint\Plugin;
class AdManager {
// ...
}
To hook the adsense
method of the AdManager
class to the before_post_content
action, you must prepend the class name with the namespace like so:
add_action( 'before_post_content', array( SitePoint\Plugin\AdManager::get_instance(), 'adsense' ) );
If the class
and the add_action
function call is in the same PHP file namespaced by SitePoint\Plugin\
, prepending the namespace to the class name is unnecessary because they are covered by the same global namespace.
Enough of class examples, let’s now see a plain function.
Say you have the following namespaced function to be hooked to the wp_head
action.
namespace SitePoint\Plugin;
function google_site_verification() {
echo '<meta name="google-site-verification" content="ytl89rlFsAzH7dWLs_U2mdlivbrr_jgV4Gq7wClHDUJ8" />';
}
Here’s how it can be done with the namespace prepended to the function:
add_action( 'wp_head', 'SitePoint\Plugin\google_site_verification' );
My Namespace Horror with the Hook System
In my Admin Bar & Dashboard Access Control plugin, I registered an uninstall hook that deletes the plugin option when it’s uninstalled.
Something as easy as the following lines of code shouldn’t be a problem where PP_Admin_Bar_Control
is the class name and on_uninstall
is the method called when uninstalled.
register_uninstall_hook( __FILE__, array( 'PP_Admin_Bar_Control', 'on_uninstall' ) );
To be sure it works, I tried uninstalling the plugin to see if the plugin option will be deleted but to my surprise, I got the following error.
The plugin generated 2137 characters of unexpected output during activation.
Mind you, here is how the class and register_uninstall_hook
function are defined with a namespace of ProfilePress\PP_Admin_Bar_Control
.
namespace ProfilePress\PP_Admin_Bar_Control;
register_uninstall_hook( __FILE__, array( 'PP_Admin_Bar_Control', 'on_uninstall' ) );
class PP_Admin_Bar_Control {
// ...
/** Callback to run when the uninstalled hook is called. */
public static function on_uninstall() {
if ( ! current_user_can( 'activate_plugins' ) ) {
return;
}
delete_option( 'abdc_options' );
}
// ...
}
Can you spot the reason why the on_uninstall
class method wasn’t triggered when the plugin is uninstalled?
You would think since the register_uninstall_hook
function is defined under the namespace, the class should be covered by it, but that is not the case. You still need to prepend the namespace to the class as follows for it to work.
register_uninstall_hook( __FILE__, array( 'ProfilePress\PP_Admin_Bar_Control\PP_Admin_Bar_Control', 'on_uninstall' ) );
I actually had a hard time figuring out the problem. I decided I don’t want to let you go through the same stress and head-banging that I went through.
Conclusion
Quirks like this make some developers cringe and stay away from WordPress. We shouldn’t forget WordPress was developed at the time when PHP lacked all the language improvement and features it has now. I always try to figure out how to circumvent these quirks and then teach it to people.
I hope I have been able to demystify the hook system in WordPress. If you have any questions or contributions, please let us know in the comments.
Collins is a web developer and freelance writer. Creator of the popular ProfilePress and MailOptin WordPress plugins. When not wrangling with code, you can find him writing at his personal blog or on Twitter.