Make WordPress PHP Class Instances Available to Developers

Removing hook that uses function or static method as a callback is simple with remove_filter() or remove_action() functions because you know exactly what callback was attached to some hook.

It gets a little tricky when your callback is an object and that object is not made available so you can’t unhook it. Consider following, simple example.

Lets say that some plugin has the following code:

class MD_Unhookable_Class {
  public function __construct() {
    add_filter( 'the_content', array( $this, 'lorem_ipsum' ) );
    add_filter( 'the_title',   array( $this, 'lorem_ipsum' ) );
  }

  public function lorem_ipsum( $content ) {
    return 'Lorem Ipsum';
  }
}

new MD_Unhookable_Class;

What this does is that it replaces text of post titles and content with Lorem Ipsum string. Now you want to remove hook that changes titles and leave hook for content. Well, you can’t. Class instance that was attached to hook was not made available because it simply called new MD_Unhookable_Class; without making its instance available.

There were some workarounds but changes in WP 4.7 will make this obsolete anyway.

Instead of instantiating class without storing its instance, lets store that instance, for example, in a global variable $md_hookable_class:

class MD_Unhookable_Class {
  public function __construct() {
    add_filter( 'the_content', array( $this, 'lorem_ipsum' ) );
    add_filter( 'the_title',   array( $this, 'lorem_ipsum' ) );
  }

  public function lorem_ipsum( $content ) {
    return 'Lorem Ipsum';
  }
}

$GLOBALS['md_hookable_class'] = new MD_Unhookable_Class;

Now you only need to use this global to remove callback:

remove_filter( 'the_title', array( $GLOBALS['md_hookable_class'], 'lorem_ipsum') );

This is just example, you don’t have to use global variable to store class instance, you can have static method in a class that instantiate class and stores that instance, or you can instantiate class inside another class and store instance as class property.

Same thing applies to anonymous functions when used as callbacks, there is no way to unhook them.

When your code is public and you use PHP classes for development, I recommend that you make class instances available so that other developers using your plugin or theme can simply unhook things that they don’t need or need differently. Also, I recommend that you avoid anonymous functions in public code for the same reason.

6 thoughts on “Make WordPress PHP Class Instances Available to Developers


  1. If the class uses an internal instance variable you can use it to unhook the action.
    I recently used this method in a class that had the following:

    protected static $_instance = null;
    public static function instance()
    {
        if (is_null(self::$_instance)) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
    add_action('woocommerce_email_before_order_table', array(&$this, 'email_display'));
    

    so I was able to use:
    remove_action('woocommerce_email_before_order_table', array(TheClassName::instance(), 'email_display'));
    to unhook it.


    1. Well, the point of this post was that plugin authors should enable something like in your example. 🙂 Maybe I wasn’t clear, it doesn’t matter how you store instance, it is only important that it’s publicly accessible.

      Personally, I use similar code, difference is that I store instance inside method’s static variable so there is no way that anyone change it:

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


      1. I understand the aim of the post.
        I was providing another example so that people would know how to unhook the function when they see an $instance variable in a class.
        I’ve never seen $GLOBALS being used to instantiate a class.


        1. $GLOBALS['md_hookable_class'] = new MD_Unhookable_Class; is just a simpler form of global $md_hookable_class;  $md_hookable_class = new MD_Unhookable_Class;. WordPress core uses it.

          I thought that providing simple, short example would make this more understandable.


          1. I’m not arguing with you 🙂

            Your example did make the concept more understandable. Thanks for the wp-settings.php link. Good to know.

            I included some code to show another way that the instance can be made publicly accessible and how to unhook a function in that scenario.

Leave a Reply

Comment Guidelines:
  • Your email address will not be published
  • Fields marked with * are required
  • If you want your picture next to comment, open an account at Gravatar
  • If you want to know if someone replied to your comment, check “Notify me of followup comments via e-mail”
  • You can use these HTML tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>