Action виконує побічну дію в певній точці життєвого циклу й нічого не повертає; filter отримує значення, змінює його й обовʼязково повертає.
Хуки — це спосіб WordPress дозволити чужому коду втрутитись у свій без правки ядра. Action виконує побічну дію в певній точці: щось вивести, записати в лог, надіслати лист. Він нічого не повертає. Filter отримує значення, наприклад заголовок або контент, змінює його й повертає далі по ланцюжку. Внутрішньо обидва живуть в одному реєстрі WP_Hook, і add_action є обгорткою над add_filter; різниця лише в тому, чи використовується результат.
Найчастіша помилка новачків — фільтр без return. Колбек повертає null, null іде далі по ланцюжку і в код, який викликав apply_filters, і на сайті зникають заголовки, контент чи ціни. WordPress не перевіряє тип результату, тому помилка тиха.
Порядок задається пріоритетом: менше число виконується раніше, за замовчуванням 10. Якщо два плагіни фільтрують the_content з однаковим пріоритетом, результат залежить від порядку завантаження, і саме звідси більшість конфліктів. Четвертий аргумент accepted_args визначає, скільки параметрів отримає колбек; без нього другий аргумент фільтра не прийде.
Щоб зняти чужий хук, remove_filter потребує те саме імʼя, той самий колбек і той самий пріоритет. Тому у власних плагінах хуки краще реєструвати іменованими функціями або методами з доступним екземпляром, а не анонімними замиканнями.
// Action: побічна дія, нічого не повертає
add_action('wp_footer', function (): void {
echo '<!-- rendered at '.date('c').' -->';
});
// Filter: отримує значення й ОБОВʼЯЗКОВО повертає
add_filter('the_title', function (string $title, int $postId): string {
return is_admin() ? $title : trim($title).' ✦';
}, 10, 2); // пріоритет 10, колбек приймає 2 аргументи
// Класична помилка: контент зникає, бо повертається null
add_filter('the_content', function (string $content): void {
str_replace('[year]', date('Y'), $content); // немає return
});
// Свій код стає розширюваним
function shop_shipping_cost(int $cents): int
{
return (int) apply_filters('shop_shipping_cost', $cents);
}
do_action('shop_order_shipped', $orderId);
// Знімаємо чужий хук: імʼя + колбек + пріоритет мають збігатись
add_action('init', fn () => remove_filter('the_content', 'wpautop', 10), 20);
Додайте, що пріоритет хука визначає порядок, і конфлікти плагінів найчастіше саме через однакові пріоритети. Згадайте apply_filters і do_action як точки, де ваш код сам стає розширюваним.