[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