Function Documentation

WordPress Function Documentation Progress

Writing Plugins: What is the Class Callback Format?

Prior to WordPress 2.3.0, there was a bug that prevented object referenced method callbacks from being removed. In WordPress 2.3.x and upcoming WordPress 2.5, in order to remove the original method in the class, you have to use the original object reference. In PHP4, where objects are passed by value, this can be a problem, but PHP5 users shouldn’t have much to worry about as long as the variable they are using holds the original class reference.

Explanation of Problem Prior to WordPress 2.3

To demonstrate the problem, take a look at this code. If you were to run this prior to WordPress 2.3, the hook would not be removed because you changed the class property $test.

class MyPlugin
{
    var $test;

    function MyPlugin() {
        $this->test = false;
        add_action('init', array(&$this, '_init'));
        $this->test = true;
    }

    function init() {
        remove_action('init', array(&$this, '_init));
    }
}

This is a poor example, in that the ‘init’ hook will never run again. Other hooks will demonstrate the problem better in real world practice. That said, the method of adding callbacks to the hook array wouldn’t have allowed you to remove the hook until the state of the class was back in its original form prior to the addition of adding the MyPlugin::_init() to the init hook.

It is a little complicated to explain, but basically, once you changed the properties of the class, you wouldn’t be able to remove any hook you added prior to the change. For most plugins this was a huge deal since they had everything in one Singleton class (big mistake, will detail in later post).

How Method Callbacks are handled in WordPress 2.3+

A new private function was introduced to manage object referenced method callbacks. The form of which is below.

$myplugin = new MyPlugin();

add_action( 'init', array(&$myplugin, '_init') );

As you can see, the callback references the $myplugin variable along with the method in the second element. The reason this can cause a problem, is if you unset the variable afterwards.

$myplugin = new MyPlugin();

add_action( 'init', array(&$myplugin, '_init') );

unset($myplugin);

If you think this will magically remove the reference in the hook array, you are mistaken. PHP will retain the reference to the object and will call the method. This will hinder, but not prevent the removal of the object’s callbacks later.

For a workaround, you can recreate the object reference and it should (purely conjecture) recreate the needed hook string to reference to previously added object reference callback. This will not work if two or more object references of the same class were created, so it is assumed that in most cases only one object reference will be created. If only one were created and destroyed, it might be possible to remove the callbacks from the action or filter using the Plugin API.

New format

The new format for the above object referenced method callbacks are always: class name, followed immediately by the method name, followed by the amount of previously added (classname+methodname). For classes, this allows you to add as many object referenced classes and add methods which don’t override each other.

For static method callbacks, the format is always: class name followed immediately by method name. There is no need to protect against overrides because no two classes can have the same class name (yes, I do know there is an exception to this rule).

For functions, nothing changes, it is just the function name.

Advertisements

January 13, 2008 Posted by | Writing Plugins Series | , , , | 5 Comments