«این ویجت را چطور از فوتر حذف کنم؟» — این سؤال را سال‌ها پیش از یک مشتری شنیدم که از یک افزونهٔ جانبی، یک جعبهٔ تبلیغاتی به فوتر سایتش اضافه شده بود و هیچ راهی برای غیرفعال‌کردنش از پیشخوان نداشت. من به‌جای ویرایش فایل افزونه (که در آپدیت بعدی پاک می‌شد)، یک remove_action در چایلد تم نوشتم. سه خط کد، مشکل را برای همیشه حل کرد. از آن روز، حذف اکشن هوک‌ها به یکی از مهارت‌های روزمرهٔ من در پروژه‌های وردپرسی تبدیل شد. اگر با مفاهیم پایه آشنا نیستید، پیش از ادامه هوک‌های وردپرس چیست، تفاوت اکشن و فیلتر در وردپرس و نحوه استفاده از add_action را بخوانید. مکمل این مقاله حذف فیلتر هوک وردپرس، مهم‌ترین اکشن هوک‌های وردپرس، راهنمای حرفه‌ای کار با هوک‌ها و ساخت اکشن سفارشی است.

اکشن هوک چیست و چرا حذف آن لازم می‌شود؟

اکشن هوک، نقطه‌ای در چرخه اجرای وردپرس است که هسته در آن، به همه اعلام می‌کند «من همین حالا این کار را انجام دادم؛ اگر کسی می‌خواهد در واکنش به آن کاری بکند، الان زمانش است». برخلاف فیلتر که داده‌ای را می‌گیرد و تغییر می‌دهد، اکشن داده‌ای را نه می‌گیرد و نه برمی‌گرداند؛ فقط اعلام رخداد است. به همین دلیل، در callback اکشن، چیزی را return نمی‌کنیم. توضیح کامل در هوک‌های وردپرس چیست و تفاوت اکشن و فیلتر.

حذف اکشن هوک، در سه سناریوی اصلی لازم می‌شود:

  1. حذف یک قابلیت افزونه یا قالب دیگر: افزونه‌ای یک ویجت تبلیغاتی در فوتر درج می‌کند و راهی برای غیرفعال‌کردن آن ندارد. با remove_action، بدون ویرایش کد افزونه، آن را حذف می‌کنید.
  2. تغییر رفتار قالب والد در چایلد تم: به‌جای override فایل‌های template، اکشن‌های قالب والد را حذف و نسخهٔ سفارشی خود را جایگزین می‌کنید.
  3. جلوگیری از اجرای یک اکشن در شرایط خاص: مثلاً می‌خواهید یک اکشن فقط در صفحات خاص اجرا نشود. با remove_action شرطی، این کار ممکن می‌شود.

راهنمای تکمیلی در هوک‌های وردپرس، ساختار هسته وردپرس، هوک‌ها در توسعه افزونه، هوک‌ها در توسعه قالب و هوک‌های خروجی قالب آمده است.

حذف اکشن هوک، مثل برداشتن یک قطعه از لِگو است: بدون شکستن کل ساختار، قطعهٔ اضافه را برمی‌دارید و ساختار را تمیز می‌کنید.

تابع remove_action: نحو و پارامترها

تابع اصلی حذف اکشن، remove_action است. نحو آن دقیقاً مشابه add_action است:

remove_action( $hook_name, $callback, $priority );

// مثال ساده
remove_action( 'wp_footer', 'myplugin_add_footer_signature', 10 );

// حذف اکشن با متد کلاس
remove_action( 'init', array( 'My_Class', 'method_name' ), 20 );

سه پارامتر کلیدی: یک — نام هوک: رشته‌ای که نقطه اتصال را مشخص می‌کند. دو — callback: تابع یا متد کلاسی که باید حذف شود. سه — priority: عددی که در زمان ثبت استفاده شده است. اگر priority را اشتباه بدهید، حذف انجام نمی‌شود. راهنمای کامل در نحوه استفاده از add_action، حذف فیلتر هوک، Priority در هوک‌ها و کنترل ترتیب اجرای هوک‌ها.

نکته حیاتی: remove_action باید بعد از ثبت اکشن اجرا شود. اگر می‌خواهید اکشن افزونه‌ای را حذف کنید، کد حذف شما باید بعد از bootstrap آن افزونه اجرا شود. معمولاً از هوک init با priority بالاتر یا wp_loaded استفاده می‌کنم. راهنمای کامل در هوک‌های وردپرس و راهنمای حرفه‌ای هوک‌ها.

اهمیت priority در حذف اکشن

یکی از پرتکرارترین خطاها در حذف اکشن، اشتباه در priority است. اگر اکشن با priority ۱۰ ثبت شده باشد و شما با priority ۲۰ حذف کنید، حذف نمی‌شود. برای اطمینان، همیشه priority را دقیقاً مطابق با ثبت بدهید:

// ثبت با priority 15
add_action( 'wp_footer', 'myplugin_footer_text', 15 );

// حذف با همان priority
remove_action( 'wp_footer', 'myplugin_footer_text', 15 );

اگر از priority ثبت‌شده مطمئن نیستید، می‌توانید از global $wp_filter برای بررسی استفاده کنید:

global $wp_filter;
if ( isset( $wp_filter['wp_footer'] ) ) {
    error_log( print_r( $wp_filter['wp_footer'], true ) );
}

راهنمای دقیق priority در Priority در هوک‌ها، کنترل ترتیب اجرای هوک‌ها، پارامترهای هوک و استفاده درست از هوک‌ها آمده است.

priority در حذف اکشن، مثل کلید در قفل است: اگر شمارهٔ کلید را اشتباه بدهید، قفل باز نمی‌شود.

حذف اکشن از کلاس‌ها

بسیاری از افزونه‌ها و قالب‌های حرفه‌ای، اکشن‌ها را در کلاس‌ها ثبت می‌کنند. برای حذف این اکشن‌ها، باید نام کلاس و متد را دقیقاً مطابق با ثبت بدهید:

// ثبت در کلاس
class My_Plugin {
    public function __construct() {
        add_action( 'init', array( $this, 'register_post_type' ), 10 );
    }
    public function register_post_type() { /* ... */ }
}

// حذف از کلاس
// اگر نمونهٔ کلاس در دسترس است:
$my_plugin = new My_Plugin();
remove_action( 'init', array( $my_plugin, 'register_post_type' ), 10 );

// یا اگر متد استاتیک است:
remove_action( 'init', array( 'My_Plugin', 'register_post_type' ), 10 );

نکته: اگر متد private یا protected باشد، حذف آن از بیرون کلاس ممکن نیست. در این حالت، باید از فیلتر یا روش‌های دیگر استفاده کنید. راهنمای کامل در کدنویسی اختصاصی افزونه، ساختار فایل‌های افزونه استاندارد، توسعه افزونه از صفر و اصول کدنویسی تمیز.

حذف اکشن از قالب والد در چایلد تم

یکی از پرکاربردترین سناریوهای حذف اکشن، حذف اکشن‌های قالب والد در چایلد تم است. به‌جای override فایل‌های template، اکشن‌های والد را حذف و نسخهٔ سفارشی خود را جایگزین می‌کنید:

// در functions.php چایلد تم
add_action( 'after_setup_theme', 'my_child_remove_parent_actions' );

function my_child_remove_parent_actions() {
    // حذف اکشن قالب والد برای نمایش نویسنده
    remove_action( 'mytheme_after_content', 'mytheme_author_box', 10 );
    
    // افزودن نسخه سفارشی
    add_action( 'mytheme_after_content', 'my_child_author_box', 10 );
}

function my_child_author_box() {
    // نسخه سفارشی
}

نکته: حذف اکشن والد باید پس از after_setup_theme انجام شود تا مطمئن شوید قالب والد توابع خود را ثبت کرده است. راهنمای کامل در قالب چایلد چیست، توسعه با چایلد تم، ساختار فایل‌های قالب استاندارد، توسعه قالب از صفر و هوک‌ها در توسعه قالب آمده است.

حذف اکشن‌های افزونه‌های دیگر

گاهی نیاز دارید اکشن‌های یک افزونهٔ دیگر را حذف کنید. برای این کار، باید نام دقیق تابع یا متد کلاس آن افزونه را بدانید. معمولاً با مراجعه به مستندات افزونه یا بررسی کد آن، این نام را پیدا می‌کنید:

// حذف اکشن افزونه دیگر
remove_action( 'wp_head', 'other_plugin_add_meta' );

// اگر در کلاس است
remove_action( 'wp_head', array( 'Other_Plugin_Class', 'add_meta' ), 10 );

نکته: اگر اکشن با closure ثبت شده باشد، قابل حذف نیست. این محدودیت، دلیل مهمی است که در افزونه‌های حرفه‌ای callbackها را به‌صورت متد کلاس یا تابع نام‌دار تعریف می‌کنیم. راهنمای کامل در حذف فیلتر هوک، استفاده درست از هوک‌ها، اشتباهات رایج هوک‌ها، کدنویسی اختصاصی افزونه و ساختار فایل‌های افزونه استاندارد.

حذف اکشن از افزونه دیگر، مثل برداشتن یک آجر از دیوار است: باید بدانید کدام آجر را بردارید تا دیوار فرو نریزد.

حذف اکشن‌های شرطی

گاهی می‌خواهید یک اکشن فقط در شرایط خاص حذف شود. مثلاً فقط در صفحهٔ اصلی، یا فقط برای کاربران مهمان. برای این کار، از حذف شرطی استفاده کنید:

add_action( 'wp', 'my_conditional_remove_action' );

function my_conditional_remove_action() {
    if ( is_front_page() && ! is_user_logged_in() ) {
        remove_action( 'wp_footer', 'myplugin_add_footer_banner', 10 );
    }
}

نکته: هوک wp بعد از تشخیص نوع درخواست اجرا می‌شود و توابع شرطی مثل is_front_page در آن قابل اعتماد هستند. راهنمای کامل در هوک‌های وردپرس، استفاده درست از هوک‌ها، بررسی وضعیت ورود کاربر، توابع نقش و دسترسی و کنترل ترتیب اجرای هوک‌ها آمده است.

اشتباهات رایج در حذف اکشن

فهرست کوتاه اما گران‌قیمت از اشتباهاتی که در کدهای بازبینی‌شده دیده‌ام:

  • priority اشتباه: شایع‌ترین اشتباه. اگر priority ثبت ۱۵ باشد و شما ۱۰ بدهید، حذف نمی‌شود. راهنما در Priority در هوک‌ها.
  • حذف قبل از ثبت: اگر کد حذف شما قبل از bootstrap افزونه اجرا شود، اکشنی برای حذف وجود ندارد. راهنما در کنترل ترتیب اجرای هوک‌ها.
  • حذف closure: اکشن‌هایی که با تابع ناشناس ثبت شده‌اند، قابل حذف نیستند. راهنما در استفاده درست از هوک‌ها.
  • نبود بررسی وجود اکشن: اگر اکشن وجود نداشته باشد، remove_action خطا نمی‌دهد ولی کاری هم نمی‌کند. برای اطمینان، از has_action استفاده کنید. راهنما در توابع دیباگ وردپرس.
  • حذف از قالب والد به‌جای چایلد: اگر در قالب والد حذف کنید، با آپدیت قالب، حذف شما پاک می‌شود. راهنما در قالب چایلد چیست.
  • نبود مستندسازی: سه ماه بعد، دلیل حذف اکشن گم می‌شود. راهنما در اصول کدنویسی تمیز.

فهرست کامل اشتباهات در اشتباهات رایج هوک‌ها، اشتباهات رایج توسعه وردپرس و اشتباهات رایج کدنویسی وردپرس آمده است.

دیباگ اکشن‌های حذف‌شده

وقتی اکشنی حذف نمی‌شود، سه ابزار در پروژه‌های خودم استفاده می‌کنم:

یک تجربه میدانی: در پروژه‌ای، یک اکشن حذف نمی‌شد. با global $wp_filter، کشف شد که افزونه‌ای دیگر همان callback را با priority متفاوت ثبت کرده و حذف ما فقط یکی از آن‌ها را برداشته است. با حذف هر دو priority، مشکل حل شد. راهنمای کامل در تست و دیباگ پروژه‌های وردپرس، دیباگ کد سفارشی و خطای Deprecated در PHP.

بهترین روش‌ها و الگوهای حرفه‌ای

در پروژه‌های بزرگ، حذف اکشن‌ها را در یک نقطه متمرکز کنید:

class My_Plugin_Remove_Actions {
    public static function init() {
        add_action( 'after_setup_theme', array( __CLASS__, 'remove_parent_actions' ) );
        add_action( 'wp', array( __CLASS__, 'conditional_removals' ) );
    }

    public static function remove_parent_actions() {
        remove_action( 'mytheme_after_content', 'mytheme_author_box', 10 );
    }

    public static function conditional_removals() {
        if ( is_front_page() ) {
            remove_action( 'wp_footer', 'myplugin_add_footer_banner', 10 );
        }
    }
}
My_Plugin_Remove_Actions::init();

مزیت: خوانایی، امکان تست، و مدیریت ترتیب اجرا. الگوهای مشابه در کدنویسی اختصاصی افزونه، ساختار فایل‌های افزونه استاندارد، توسعه افزونه از صفر، استانداردهای کدنویسی وردپرس، بهینه‌سازی کد وردپرس و ساختاربندی پروژه وردپرس آمده است.

یک تجربه میدانی: در پروژه‌ای با سه افزونه اختصاصی که هرکدام چند اکشن را حذف می‌کردند، انتقال به این الگو در یک کلاس متمرکز، زمان دیباگ تعارض‌ها را از چند ساعت به چند دقیقه کاهش داد.

حذف اکشن در ووکامرس: مثال‌های واقعی

در فروشگاه‌های ووکامرسی، حذف اکشن‌ها برای سفارشی‌سازی رابط کاربری ضروری است:

// حذف پیام اضافه‌شده به صفحه محصول
remove_action( 'woocommerce_before_single_product', 'woocommerce_output_all_notices', 10 );

// حذف عنوان محصول از صفحه محصول
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_title', 5 );

// حذف تصویر شاخص از صفحه محصول
remove_action( 'woocommerce_before_single_product_summary', 'woocommerce_show_product_images', 20 );

راهنمای کامل در هوک‌های ووکامرس، مدیریت سفارش‌های ووکامرس، سفارشی‌سازی صفحه محصول، سفارشی‌سازی سبد و تسویه‌حساب، راهنمای کار با ووکامرس و ووکامرس چیست آمده است.

جمع‌بندی

حذف اکشن هوک در وردپرس، در چهار اصل خلاصه می‌شود: شناخت دقیق priority، اجرای حذف پس از ثبت، استفاده از callback نام‌دار، و متمرکزسازی حذف‌ها در یک کلاس. سه اصل را در پایان تاکید می‌کنم: اول، همیشه priority را مطابق با ثبت بدهید. دوم، حذف را در چایلد تم یا افزونه اختصاصی انجام دهید، نه در قالب والد. سوم، از حذف closureها پرهیز کنید؛ اگر افزونه‌ای closure دارد، به‌جای حذف، از فیلترهای دیگر استفاده کنید.

اگر امروز یک کار در این مسیر انجام می‌دهید: در پروژه فعلی خود، فهرست اکشن‌هایی که افزونه‌ها یا قالب اضافه کرده‌اند و شما نمی‌خواهید را بنویسید و برای هرکدام یک remove_action با priority درست بنویسید. همان یک بازبینی، در آپدیت بعدی نجات‌دهنده است. اگر تجربه‌ای از یک حذف اکشن دارید که پروژه‌ای را نجات داد یا باگی را حل کرد، در دیدگاه‌ها بنویسید — همان گزارش‌های واقعی، این راهنما را برای توسعه‌دهنده بعدی دقیق‌تر می‌کند. 🔗