Как удалить фильтр, анонимный объект?

В моем файле functions.php я хотел бы удалить фильтр ниже, но я не уверен, как это сделать, поскольку он находится в классе. Что должно выглядеть remove_filter ()?

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

В строке 88 здесь .

60 голосов | спросил Jonas 1 J000000Sunday12 2012, 12:02:10

3 ответа


75

Это очень хороший вопрос. Он переходит к темному сердцу API плагина и наилучшим практикам программирования.

Для следующего ответа я создал простой плагин, чтобы проиллюстрировать проблему с легко читаемым кодом.

<? php # - * - кодирование: utf-8 - * -
/* Название плагина: Анонимное действие ООП * /

if (! class_exists ('Anonymous_Object'))
{
    /**
     * Добавьте некоторые действия со случайными глобальными идентификаторами.
     * /
    класс Anonymous_Object
    {
        публичная функция __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);
        }

        публичная функция print_message_1 ()
        {
            print '<p> Убейте меня! </p>';
        }

        публичная функция print_message_2 ()
        {
            print '<Me тоже! </p>';
        }

        публичная функция print_message_3 ()
        {
            print '<p> Aaaand me! </p>';
        }
    }

    //Удача найти меня!
    новый анонимный_объект;
}

Теперь мы видим следующее:

введите описание изображения здесь>> </p>

<p> Для фильтра WordPress требуется <strong> имя </strong>. Мы этого не сделали, поэтому WordPress вызывает <a href= _wp_filter_build_unique_id () и создает один. Это имя не предсказуемо, поскольку оно использует spl_object_hash () .

Если мы запустим var_export () на $ GLOBALS [' wp_filter '] [' wp_footer '] теперь мы получаем что-то вроде этого:

массив (
  5 =>
  массив (
    '000000002296220e0000000013735e2bprint_message_1' =>
    массив (
      'function' =>
      массив (
        0 =>
        Anonymous_Object :: __ set_state (массив (
        )),
        1 => 'Print_message_1',
      ),
      'accepted_args' => 1,
    ),
    '000000002296220e0000000013735e2bprint_message_2' =>
    массив (
      'function' =>
      массив (
        0 =>
        Anonymous_Object :: __ set_state (массив (
        )),
        1 => 'Print_message_2',
      ),
      'accepted_args' => 1,
    ),
  ),
  12 =>
  массив (
    '000000002296220e0000000013735e2bprint_message_3' =>
    массив (
      'function' =>
      массив (
        0 =>
        Anonymous_Object :: __ set_state (массив (
        )),
        1 => 'Print_message_3',
      ),
      'accepted_args' => 1,
    ),
  ),
  20 =>
  массив (
    'wp_print_footer_scripts' =>
    массив (
      'function' => 'wp_print_footer_scripts',
      'accepted_args' => 1,
    ),
  ),
  1000 =>
  массив (
    'wp_admin_bar_render' =>
    массив (
      'function' => 'Wp_admin_bar_render',
      'accepted_args' => 1,
    ),
  ),
)

Чтобы найти и удалить наше действие зла, нам нужно пройти через связанные фильтры для крюка (действие - это очень простой фильтр), проверьте, является ли он массивом, и если объект является экземпляром класса. Затем мы берем приоритет и удаляем фильтр , не видя реального идентификатора .

Хорошо, letâ € ™ s поместить это в функцию:

if (! function_exists ('remove_anonymous_object_filter'))
{
    /**
     * Удалить фильтр анонимных объектов.
     *
     * @param string $ tag Имя крюка.
     * @param string $ class Имя класса
     * @param string $ method Имя метода
     * @return void
     * /
    function remove_anonymous_object_filter ($ tag, $ class, $ method)
    {
        $ filters = $ GLOBALS ['wp_filter'] [$ tag];

        if (empty ($ filters))
        {
            вернуть;
        }

        foreach ($ фильтры как $ priority => $ filter)
        {
            foreach ($ filter as $ identifier => $ function)
            {
                if (is_array ($ function)
                    и is_a ($ function ['function'] [0], $ class)
                    и $ method === $ function ['function'] [1]
                )
                {
                    remove_filter (
                        $ Тег,
                        array ($ function ['function'] [0], $ method),
                        $ приоритет
                    );
                }
            }
        }
    }
}

Когда мы называем эту функцию? Невозможно точно знать, когда будет создан исходный объект. Может быть, иногда до 'plugins_loaded'? Может быть позже?

Мы используем тот же самый крючок, с которым связан объект, и прыгаем очень рано с приоритетом 0. Это единственный способ быть уверенным. Вот как мы удалим метод print_message_3 ():

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

функция kill_anonymous_example ()
{
    remove_anonymous_object_filter (
        'Wp_footer',
        'Anonymous_Object',
        'Print_message_3'
    );
}

Результат:

введите описание изображения здесь>> </p>

<p> И это должно удалить действие из вашего вопроса (не проверено): </p>

<pre><code>add_action ('comments_array', 'kill_FbComments', 0);

функция kill_FbComments ()
{
    remove_anonymous_object_filter (
        'Comments_array',
        'SEOFacebookComments',
        'FbComments'
    );
}
</code></pre>

<H2> Заключение </h2>

<ul>
<li> Всегда пишите прогнозируемый код. Установите читаемые имена для ваших фильтров и действий. Удалите любой крючок. </li>
<li> Создайте свой объект в предсказуемом действии, например, в <code>'plugins_loaded'</code>. Не только когда ваш плагин вызывается WordPress. </li>
</ul></div>
					 
						<div class=

ответил fuxia 1 J000000Sunday12 2012, 15:25:52
0

Я не уверен, но вы можете попробовать использовать синглтон.
Вы должны сохранить ссылку на объект в статическом свойстве своего класса, а затем вернуть статическую переменную из статического метода. Что-то вроде этого:

класс MyClass {
    private static $ ref;
    функция MyClass () {
        $ ref = & $ this;
    }
    public static function getReference () {
        return self :: $ ref;
    }
}
ответил Hamed Momeni 1 J000000Sunday12 2012, 14:41:00
0

Пока вы знаете объект (и используете 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]));

И все.

ответил hakre 28 J000000Sunday13 2013, 15:59:21

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132