Как удалить фильтр, анонимный объект?
В моем файле functions.php
я хотел бы удалить фильтр ниже, но я не уверен, как это сделать, поскольку он находится в классе. Что должно выглядеть remove_filter ()
?
add_filter ('comments_array', array (& $ this, 'FbComments'));
В строке 88 здесь .
3 ответа
Это очень хороший вопрос. Он переходит к темному сердцу 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>';
}
}
//Удача найти меня!
новый анонимный_объект;
}
Теперь мы видим следующее:
_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'
);
}
Результат:
Я не уверен, но вы можете попробовать использовать синглтон.
Вы должны сохранить ссылку на объект в статическом свойстве своего класса, а затем вернуть статическую переменную из статического метода. Что-то вроде этого:
класс MyClass {
private static $ ref;
функция MyClass () {
$ ref = & $ this;
}
public static function getReference () {
return self :: $ ref;
}
}
Пока вы знаете объект (и используете 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]));
И все.