[wp-hackers] Passing class methods by reference

Jacob Santos wordpress at santosj.name
Thu Aug 5 23:27:57 UTC 2010


The suggestion was always to use static methods to reduce the overhead 
and prevent bugs such as what the WordPress developers keep trying to 
fix. The problem is also that we require the reference to the original 
object, in order to properly set and look at the filter_id assign to the 
object. The entire bit of code was first added during the WordPress 2.3 
cycle, to show how long the problem has been evolving. The problem was 
added in 2.2 when optimizations to the filter system broken all classes.

Much of the problem is that it relies heavily on the competence of the 
plugin developers in setting the reference to the object and in the 
ability to pull back the reference to that object.

Part of the problem also, is that you need a reference to the original 
object. If some plugin programmer does array(&$this, 'method'); then you 
need to access the object by finding and using the global that the 
plugin programmer used to call the constructor.

Say for instance someone did this:

function _my_plugin_init() {
     $my_class = new My_Class(); // Constructor sets hooks.
}

_my_plugin_init();

You would never have access to the original object instance as once the 
local scope goes away, access to $my_class will no longer be available. 
However, since the reference to $my_class will still be referenced by 
the plugin API, it will keep the plugin working. This leaves you without 
the ability to remove the plugin filter. With the fixes to the filter id 
system, it is impossible to recreate the object to remove the object.

If the plugin is a global, which unfortunately is the best case Michael, 
you should be able to do: remove_action('init', array(&$my_class, 
'method'));


On 8/5/2010 1:57 PM, Michael D Adams wrote:
> On Thu, Aug 5, 2010 at 11:21 AM, Andrew Nacin<wp at andrewnacin.com>  wrote:
>    
>> class my_class {
>>    function __construct() {
>>      add_action( 'init', array(&$this, 'init' ) );
>>    }
>>    function init() {}
>> }
>> $my_class_instance = new my_class;
>> remove_action( 'init', array( $my_class_instance, 'init' ) );
>>
>> This is generally why I always assign instantiations to a variable in my
>> plugins (versus simply calling `new myclass;`), that way I'm playing nice
>> with others and allowing another plugin to modify the callbacks I attach.
>>      
> Off topic: I have an irrational hatred of globals.  I'm on a twelve
> step program and everything.
>
> What I usually do is offer to plugins some static method on my classes
> to accomplish the same thing.  In a case like this where you're using
> my_class as a singleton, it's pretty straightforward.
>
> require 'wp-load.php';
>
> class My_Class { // Nacin should ucwords() his classes :)
>          static $instance;
>          static function&instance() {
>                  // You could use a static variable here instead
>                  if ( !self::$instance )
>                          new My_Class;
>                  return self::$instance;
>          }
>
>          function __construct() {
>                  self::$instance =&  $this;
>                  add_action( 'shutdown', array(&$this, 'hola' ) );
>          }
>
>          function hola() {
>                  die( "Hola.  If you see this, this example is broken.\n" );
>          }
> }
>
> My_Class::instance();
>
> function adios() {
>          remove_action( 'shutdown', array( My_Class::instance(), 'hola' ) );
> }
>
> adios();
>
>
> Static class methods are slow, though.
> _______________________________________________
> wp-hackers mailing list
> wp-hackers at lists.automattic.com
> http://lists.automattic.com/mailman/listinfo/wp-hackers
>    



More information about the wp-hackers mailing list