如何删除作为匿名对象的筛选器?

时间:2012-07-01 作者:Jonas

在我的functions.php 文件我想删除下面的过滤器,但我不知道该怎么做,因为它在类中。应该做什么remove_filter() 看起来像

add_filter(\'comments_array\',array( &$this, \'FbComments\' ));
在88号线here.

3 个回复
最合适的回答,由SO网友:fuxia 整理而成

这是一个很好的问题。它深入到插件API和最佳编程实践的核心。

对于下面的答案,我创建了一个简单的插件,用易于阅读的代码来说明这个问题。

<?php # -*- coding: utf-8 -*-
/* Plugin Name: Anonymous OOP Action */

if ( ! class_exists( \'Anonymous_Object\' ) )
{
    /**
     * Add some actions with randomized global identifiers.
     */
    class Anonymous_Object
    {
        public function __construct()
        {
            add_action( \'wp_footer\', array ( $this, \'print_message_1\' ), 5 );
            add_action( \'wp_footer\', array ( $this, \'print_message_2\' ), 5 );
            add_action( \'wp_footer\', array ( $this, \'print_message_3\' ), 12 );
        }

        public function print_message_1()
        {
            print \'<p>Kill me!</p>\';
        }

        public function print_message_2()
        {
            print \'<p>Me too!</p>\';
        }

        public function print_message_3()
        {
            print \'<p>Aaaand me!</p>\';
        }
    }

    // Good luck finding me!
    new Anonymous_Object;
}
现在我们看到:

enter image description here

WordPress需要name 用于过滤器。我们没有提供,所以WordPress打电话_wp_filter_build_unique_id() 并创建一个。此名称不可预测,因为它使用spl_object_hash().

如果我们运行var_export() 在…上$GLOBALS[\'wp_filter\'][ \'wp_footer\' ] 我们现在得到了这样的结果:

array (
  5 => 
  array (
    \'000000002296220e0000000013735e2bprint_message_1\' => 
    array (
      \'function\' => 
      array (
        0 => 
        Anonymous_Object::__set_state(array(
        )),
        1 => \'print_message_1\',
      ),
      \'accepted_args\' => 1,
    ),
    \'000000002296220e0000000013735e2bprint_message_2\' => 
    array (
      \'function\' => 
      array (
        0 => 
        Anonymous_Object::__set_state(array(
        )),
        1 => \'print_message_2\',
      ),
      \'accepted_args\' => 1,
    ),
  ),
  12 => 
  array (
    \'000000002296220e0000000013735e2bprint_message_3\' => 
    array (
      \'function\' => 
      array (
        0 => 
        Anonymous_Object::__set_state(array(
        )),
        1 => \'print_message_3\',
      ),
      \'accepted_args\' => 1,
    ),
  ),
  20 => 
  array (
    \'wp_print_footer_scripts\' => 
    array (
      \'function\' => \'wp_print_footer_scripts\',
      \'accepted_args\' => 1,
    ),
  ),
  1000 => 
  array (
    \'wp_admin_bar_render\' => 
    array (
      \'function\' => \'wp_admin_bar_render\',
      \'accepted_args\' => 1,
    ),
  ),
)
为了找到并删除我们的邪恶行为,我们必须通过挂钩的相关过滤器(一个行为只是一个非常简单的过滤器),检查它是否是一个数组,以及对象是否是该类的实例。然后,我们取优先权并删除过滤器,,而从未看到真正的标识符。

好的,让我们把它放到一个函数中:

if ( ! function_exists( \'remove_anonymous_object_filter\' ) )
{
    /**
     * Remove an anonymous object filter.
     *
     * @param  string $tag    Hook name.
     * @param  string $class  Class name
     * @param  string $method Method name
     * @return void
     */
    function remove_anonymous_object_filter( $tag, $class, $method )
    {
        $filters = $GLOBALS[\'wp_filter\'][ $tag ];

        if ( empty ( $filters ) )
        {
            return;
        }

        foreach ( $filters as $priority => $filter )
        {
            foreach ( $filter as $identifier => $function )
            {
                if ( is_array( $function)
                    and is_a( $function[\'function\'][0], $class )
                    and $method === $function[\'function\'][1]
                )
                {
                    remove_filter(
                        $tag,
                        array ( $function[\'function\'][0], $method ),
                        $priority
                    );
                }
            }
        }
    }
}
我们什么时候调用这个函数?无法确定何时创建原始对象。也许以前有过\'plugins_loaded\'? 也许以后?

我们只使用与对象关联的同一个挂钩,并且很早就以优先级跳入0. 只有这样才能真正确定。下面是如何删除该方法print_message_3():

add_action( \'wp_footer\', \'kill_anonymous_example\', 0 );

function kill_anonymous_example()
{
    remove_anonymous_object_filter(
        \'wp_footer\',
        \'Anonymous_Object\',
        \'print_message_3\'
    );
}
结果:

enter image description here

这将从您的问题中删除操作(未测试):

add_action( \'comments_array\', \'kill_FbComments\', 0 );

function kill_FbComments()
{
    remove_anonymous_object_filter(
        \'comments_array\',
        \'SEOFacebookComments\',
        \'FbComments\'
    );
}
结论总是编写可预测的代码。为过滤器和操作设置可读名称。轻松移除任何挂钩\'plugins_loaded\'. 不仅仅是当你的插件被WordPress调用时

SO网友:2hamed

我不确定,但你可以尝试使用单件
必须将对象引用存储在类的静态属性中,然后从静态方法返回该静态变量。类似这样:

class MyClass{
    private static $ref;
    function MyClass(){
        $ref = &$this;
    }
    public static function getReference(){
        return self::$ref;
    }
}

SO网友:hakre

只要您知道该对象(并且您使用PHP 5.2或更高版本-当前稳定的PHP版本是5.5,5.4仍然受支持,5.3已经过时),就可以使用remove_filter() 方法您只需记住对象、方法名称和优先级(如果使用):

remove_filter(\'comment_array\', [$this, \'FbComments\']);
然而,您在代码中犯了一个小错误。不加前缀$this 用符号和&, 这在PHP 4中是必需的(!)早就应该这样了。这可能会导致处理挂钩出现问题,因此请不要插手:

add_filter(\'comments_array\', [$this, \'FbComments]));
就这样。

结束

相关推荐

Help with Changing loop.php?

我正在尝试编辑循环,因此如果它在类别ID 60上,它将显示“照片”,而不是“博客”。。我该怎么做?博客 <?php if(is_archive()&&!is_category()&&!is_tag()&&!is_search()){ ?> <!-- BEGIN .archive-title --> <h1 class=\"page-title\"> &