В ситуации, когда плагин инкапсулировал свои методы в классе, а затем зарегистрировал фильтр или действие для одного из этих методов, как удалить действие или фильтр, если у вас больше нет доступа к экземпляру этого класса?
Например, предположим, что у вас есть плагин, который делает это:
class MyClass {
function __construct() {
add_action( "plugins_loaded", array( $this, 'my_action' ) );
}
function my_action() {
// do stuff...
}
}
new MyClass();
Отмечая, что теперь у меня нет возможности получить доступ к экземпляру, как мне отменить регистрацию класса? Это: remove_action( "plugins_loaded", array( MyClass, 'my_action' ) );
не кажется правильным подходом - по крайней мере, в моем случае это не сработало.
Ответы:
Лучше всего использовать статический класс. Следующий код должен быть инструктивным:
Если вы запускаете этот код из плагина, вы должны заметить, что метод StaticClass, а также функция будут удалены из wp_footer.
источник
remove_action
функцию, иначе она не будет работать ... поэтому я должен был написать свою собственную функцию для обработки, когда это не статический класс. Этот ответ будет лучшим, только если ваш вопрос касается вашего собственного кода, в противном случае вы будете пытаться удалить другой фильтр / действие из чужой кодовой базы и не сможете изменить его на статическийВсякий раз, когда плагин создает
new MyClass();
, он должен назначить его переменной с уникальным именем. Таким образом, экземпляр класса доступен.Так что, если он делал
$myclass = new MyClass();
, то вы могли бы сделать это:Это работает, потому что плагины включены в глобальное пространство имен, поэтому неявные объявления переменных в основной части плагина являются глобальными переменными.
Если плагин не сохраняет идентификатор нового класса где-то , то технически это ошибка. Одним из общих принципов объектно-ориентированного программирования является то, что объекты, на которые не ссылается какая-либо переменная, подлежат очистке или удалению.
В частности, PHP, в частности, делает это не так, как Java, потому что PHP - это наполовину реализация ООП. Переменные экземпляра - это просто строки с уникальными именами объектов, что-то вроде этого. Они работают только из-за способа взаимодействия имени переменной функции с
->
оператором. Так что просто делатьnew class()
действительно может работать отлично, просто глупо. :)Итак, суть, никогда не делай
new class();
. Сделайте$var = new class();
и сделайте этот $ var доступным для других битов, чтобы ссылаться на него.Изменить: годы спустя
Одна вещь, которую я видел во многих плагинах, это использование чего-то похожего на шаблон «Синглтон». Они создают метод getInstance (), чтобы получить единственный экземпляр класса. Это, наверное, лучшее решение, которое я видел. Пример плагина:
При первом вызове getInstance () он создает экземпляр класса и сохраняет его указатель. Вы можете использовать это, чтобы подключить действия.
Одна из проблем заключается в том, что вы не можете использовать getInstance () внутри конструктора, если используете такую вещь. Это потому, что new вызывает конструктор перед установкой $ instance, поэтому вызов getInstance () из конструктора приводит к бесконечному циклу и прерывает все.
Один из обходных путей - не использовать конструктор (или, по крайней мере, не использовать внутри него getInstance ()), но явно иметь функцию «init» в классе для настройки ваших действий и тому подобного. Нравится:
Что-то вроде этого, в конце файла, после того, как класс был полностью определен и тому подобное, создание плагина становится таким простым:
Init начинает добавлять ваши действия и при этом вызывает getInstance (), который создает экземпляр класса и проверяет, существует ли только одно из них. Если у вас нет функции инициализации, вы должны сделать это для первоначального создания экземпляра класса:
Чтобы ответить на исходный вопрос, удаление этого хука действия извне (иначе в другом плагине) может быть сделано следующим образом:
Поместите это во что-то, зацепленное за
plugins_loaded
крючок действия, и оно отменит действие, зацепленное оригинальным плагином.источник
wp_loaded
, а неplugins_loaded
, что может быть названо слишком рано.plugins_loaded
было бы правильное место.wp_loaded
Действие происходит послеinit
действия, так что если ваш плагин принимает какие - либо действия наinit
(и большинство из них), то вы хотите , чтобы инициализировать плагин и установить его до этого.plugins_loaded
Крюк является правильным местом для этого этапа строительства.2 небольшие функции PHP, позволяющие удалить фильтр / действие с помощью «анонимного» класса: https://github.com/herewithme/wp-filters-extras/
источник
Вот широко документированная функция, которую я создал для удаления фильтров, когда у вас нет доступа к объекту класса (работает с WordPress 1.2+, включая 4.7+):
https://gist.github.com/tripflex/c6518efc1753cf2392559866b4bd1a53
источник
Вышеуказанные решения выглядят как устаревшие, пришлось написать свое ...
источник
Эта функция основана на ответе @Digerkam. Добавлено сравнение, если
$def['function'][0]
строка, и это, наконец, работает для меня.Также использование
$wp_filter[$tag]->remove_filter()
должно сделать его более стабильным.Пример использования:
Точное совпадение
Любой приоритет
Любой класс и любой приоритет
источник
Это не общий ответ, а специфический для темы Avada и WooCommerce , который, как я думаю, может оказаться полезным для других людей:
источник