Удаление действий из плагина в другом плагине
Я пытаюсь удалить два действия, которые добавляет плагин (конкретно sportspress). Действия этого плагина следующие:
add_action('sportspress_before_single_player','sportspress_output_player_details', 15);
add_action('sportspress_single_player_content','sportspress_output_player_statistics',20);
Я создал плагин и хочу удалить эти хуки, вот мой код:
<?php
/*
Plugin Name: my plugin
Description: Плагин для переопределения хуков других плагинов
Version: 0.1
Author: Company Name
Author URI: http://www.example.com/
License: GPL2
*/
add_action('plugins_loaded','remove_hooks');
function remove_hooks(){
remove_action( 'sportspress_before_single_player', 'sportspress_output_player_details' );
remove_action( 'sportspress_single_player_content', 'sportspress_output_player_statistics' );
}
Я искал и пробовал много разных вариантов, но не могу заставить это работать.
Есть две вещи, которые смущают людей при попытке удалить хук:
- Вызовы
remove_action()
илиremove_filter()
должны происходить после вызововadd_action()
илиadd_filter()
, и до того, как хук фактически сработает. Это означает, что вы должны знать, когда хуки были добавлены и когда они срабатывают. - Вызовы
remove_action()
илиremove_filter()
должны иметь тот же приоритет, что и вызовыadd_action()
илиadd_filter()
.
Если эти хуки были добавлены на фильтр init с приоритетом по умолчанию, то для их удаления мы просто подключаемся к init с приоритетом больше 10 и удаляем их.
add_action( 'init', 'wpse_106269_remove_hooks', 11 );
function wpse_106269_remove_hooks(){
remove_action( 'sportspress_before_single_player', 'sportspress_output_player_details', 15 );
remove_action( 'sportspress_single_player_content', 'sportspress_output_player_statistics', 20 );
}
Из https://codex.wordpress.org/Function_Reference/remove_action
Важно: Для удаления хука аргументы $function_to_remove и $priority должны совпадать с теми, которые использовались при добавлении хука. Это касается как фильтров, так и действий. При неудачном удалении предупреждение выводиться не будет.

У меня была такая же проблема. Я хотел удалить действие, которое было добавлено другим плагином, и заменить его на свою функцию в разрабатываемом мной плагине, но мой файл (как сказал @Sumit) шел после файла оригинального плагина в алфавитном порядке. Тем не менее, мне удалось удалить действие.
Что сработало в моем случае — это обернуть вызов remove_action
внутри другого add_action, чтобы он выполнялся после загрузки всех плагинов. Это можно сделать с помощью действия init:
add_action( 'init', 'changeActions' );
function changeActions () {
remove_action('my_action', 'the_function_from_the_plugin', 10);
}
P.S.: Если вы хотите проверить, были ли действия успешно удалены, вы можете вывести список функций, привязанных к нужному действию, используя код из этого ответа. Я использовал тестовый шорткод, так как не работал с файлами темы (просто добавьте [test_actions]
на любую страницу в панели WordPress).
add_shortcode('test_actions', 'testActions');
function testActions($attrs) {
//получаем список всех действий, используя эту глобальную переменную
global $wp_filter;
//получаем только действия, привязанные к 'my_action'
$r = $wp_filter['my_action'];
//возвращаем дамп массива в виде строки
return var_export($r, TRUE);
}

Плагины загружаются в порядке, соответствующем их именам файлов. Например, плагин с именем abc.php
загружается первым, а затем xyz.php
. Поэтому, если вы пытаетесь удалить действие из плагина abc.php
, которое было добавлено в плагине xyz.php
, это невозможно без дополнительных изменений. Потому что на момент попытки удаления действие еще не было добавлено.
Вы можете просто добавить die(__FILE__);
в оба плагина, чтобы увидеть, какой из них выводит результат первым. Если ваш плагин загружается раньше, вы можете сделать две вещи для удаления действия:
- Переименуйте ваш плагин, чтобы он загружался после целевого плагина.
- Я не уверен, когда выполняются родительские действия, но существует большой список действий Action_Reference, на которые вы можете повесить удаление действия в своем плагине. Теперь вы знаете, когда следует размещать
remove_action()
, чтобы это было эффективно.
Надеюсь, это поможет.

Я добавил die
, и первый загружаемый плагин является "родительским", так что не должно быть проблем с порядком загрузки плагинов

Да, тогда не должно быть проблем, удалите действие plugins_loaded
и напрямую разместите remove_action
в вашем плагине с тем же приоритетом, это будет работать в соответствии с предоставленной вами структурой кода.
