問題描述

在我的 functions.php 文件中,我想刪除下面的過濾器,但我不知道如何做,因為它在一個類中。 remove_filter()應該是什麼樣的?

add_filter('comments_array',array( &$this, 'FbComments' ));

它在線 88 here

最佳解決方案

這是一個很好的問題。它下降到插件 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;
}

現在我們看到:

WordPress 需要一個過濾器的名稱。我們沒有提供,所以 WordPress 調用_wp_filter_build_unique_id()並創建一個。這個名字是不可預測的,因為它使用 spl_object_hash()

如果我們在 $GLOBALS['wp_filter'][ 'wp_footer' ]上運行 var_export(),我們現在可以得到這樣的東西:

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'
    );
}

結果:

這應該從您的問題 (未測試) 中刪除該操作:

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

function kill_FbComments()
{
    remove_anonymous_object_filter(
        'comments_array',
        'SEOFacebookComments',
        'FbComments'
    );
}

Conclusion

  • 始終寫可預見的代碼。為您的過濾器和操作設置可讀名稱。使其輕鬆刪除任何鈎子。
  • 以可預測的方式創建對象,例如'plugins_loaded'。不只是當您的插件被 WordPress 調用時。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。