آن روزی که فهمیدم هوک، ستون فقرات وردپرس است

اولین قالب اختصاصی که نوشتم، یک قالب ساده برای یک وبلاگ شخصی بود. همه‌چیز کار می‌کرد تا روزی که صاحب سایت خواست متن فوتر را تغییر دهد. من مستقیم رفتم سراغ footer.php و کد را ویرایش کردم. یک ماه بعد، قالب را برای اضافه‌کردن یک قابلیت جدید آپدیت کردم و متن فوتر از بین رفت. مدیر سایت زنگ زد و پرسید «چرا متنی که نوشته بودم پاک شد؟» آن روز نفهمیدم که مقصر خودم بودم، نه وردپرس. سه ماه بعد، در یک پروژه دیگر، با یک توسعه‌دهنده باتجربه‌تر کار می‌کردم. وقتی از او پرسیدم «چطور می‌شود بدون تغییر دادن فایل قالب، متن فوتر را عوض کرد؟» جوابش یک کلمه بود: «هوک». همان کلمه، مسیر فنی من را برای همیشه عوض کرد. از آن روز، هر تغییری که قرار بود در وردپرس انجام دهم، اول از خودم می‌پرسیدم: «آیا هوکی برای این کار وجود دارد؟» و در ۹۰٪ موارد، جواب مثبت بود. این مقاله، همان چیزی است که از آن روز یاد گرفته‌ام — نه فهرست هوک‌ها، بلکه درک عمیق مکانیزمی که کل اکوسیستم وردپرس روی آن ساخته شده.

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

هوک چیست؟ تعریفی که از اول باید می‌دانستم

هوک (Hook) مکانیزم رسمی وردپرس است که به کد شما اجازه می‌دهد بدون تغییر هسته، در نقاط مشخصی از اجرای وردپرس وارد شود. تصور کنید وردپرس یک خط تولید است که در طول مسیر خود، در ده‌ها ایستگاه توقف می‌کند. در هر ایستگاه، این سؤال را می‌پرسد: «آیا کسی هست که بخواهد اینجا کاری انجام دهد یا چیزی را تغییر دهد؟» اگر کدی روی آن ایستگاه ثبت شده باشد، وردپرس آن را صدا می‌زند. این ایستگاه‌ها، همان هوک‌ها هستند. دو نکته بنیادین: اول، هوک فقط یک نام است؛ آنچه اجرا می‌شود، تابع (callback) شماست که روی آن هوک ثبت شده. دوم، این مکانیزم، دلیل اصلی انعطاف وردپرس است — چرا که هزاران افزونه و قالب می‌توانند بدون تعارض با هسته و با یکدیگر، در نقاط مشخصی وارد شوند. بدون هوک، هر افزونه باید فایل‌های وردپرس را مستقیماً ویرایش می‌کرد و هر آپدیت، همه چیز را می‌شکست. مفهوم کلی در افزونه وردپرس چیست و ساختار هسته وردپرس آمده است.

هوک در وردپرس، مثل پریز برق در دیوار است: هسته، پریز را می‌سازد؛ افزونه، دوشاخه را می‌زند. هیچ‌کس برای روشن‌کردن چراغ، دیوار را نمی‌شکافد.

اکشن در برابر فیلتر: تفاوت واقعی

وردپرس دو نوع هوک دارد و درک تفاوتشان، اولین گام تسلط است:

  • اکشن (Action): در لحظه مشخصی از اجرای وردپرس، کد شما اجرا می‌شود. اکشن، داده‌ای را تغییر نمی‌دهد؛ فقط کاری را انجام می‌دهد. مثال: ذخیره فایل لاگ، ارسال ایمیل، ثبت رکورد در دیتابیس. توابع add_action، do_action و remove_action ابزارهای این حوزه هستند.
  • فیلتر (Filter): در لحظه مشخصی، داده‌ای به کد شما پاس داده می‌شود، شما آن را تغییر می‌دهید و برمی‌گردانید. فیلتر، داده‌ای را تغییر می‌دهد. مثال: اضافه کردن متن به محتوای نوشته، تغییر عنوان صفحه، دست‌کاری منو. توابع add_filter، apply_filters و remove_filter ابزارهای این حوزه هستند.

یک قاعده ساده برای تشخیص: اگر می‌خواهید «کاری انجام شود»، اکشن؛ اگر می‌خواهید «داده تغییر کند»، فیلتر. اشتباه گرفتن این دو، منبع باگ‌های عجیب در ترتیب اجرا است. تفصیل کامل در هوک‌های وردپرس، تفاوت اکشن و فیلتر، و راهنمای حرفه‌ای کار با هوک‌ها آمده است.

چرخه اجرای وردپرس: هوک‌ها کجا هستند؟

برای درک عمیق هوک‌ها، باید بدانید در چرخه اجرای یک درخواست، وردپرس در چه نقاطی این ایستگاه‌ها را می‌سازد. چرخه اصلی، از wp-load.php شروع می‌شود و به رندر قالب ختم می‌شود. مهم‌ترین هوک‌ها به ترتیب زمان اجرا:

هوکزمان اجراکاربرد معمول
muplugins_loadedپس از لود افزونه‌های اجباریراه‌اندازی زیرساخت‌های حیاتی
plugins_loadedپس از لود همه افزونه‌هاراه‌اندازی اولیه افزونه
after_setup_themeپس از لود قالبتنظیمات قالب
initپس از راه‌اندازی هستهثبت post type، شورت‌کد، تاکسونومی
wp_loadedپس از بارگذاری کاملعملیات نیازمند دسترسی کامل
template_redirectقبل از رندر قالبریدایرکت، محدودسازی دسترسی
wp_headدرون تگ headافزودن متا، اسکریپت، استایل
wp_footerقبل از بستن bodyافزودن اسکریپت‌های پایانی

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

add_action و add_filter: نحو و پارامترها

دو تابع اصلی برای ثبت هوک، نحو مشخصی دارند:

add_action( $hook_name, $callback, $priority, $accepted_args );
add_filter( $hook_name, $callback, $priority, $accepted_args );

// مثال‌های ساده
add_action( 'init', 'myplugin_register_post_type' );
add_filter( 'the_content', 'myplugin_append_signature' );

// با اولویت و تعداد پارامتر
add_action( 'save_post', 'myplugin_save_data', 20, 3 );
add_filter( 'the_content', 'myplugin_modify_content', 15, 1 );

پارامترها: یک — نام هوک: رشته‌ای که نقطه اتصال را مشخص می‌کند. دو — callback: تابع یا متد کلاسی که اجرا می‌شود. سه — priority: عددی که ترتیب اجرا را تعیین می‌کند (پیش‌فرض ۱۰، عدد کمتر زودتر). چهار — accepted_args: تعداد پارامترهایی که callback دریافت می‌کند (پیش‌فرض ۱). راهنمای کامل در نحوه استفاده از add_action، نحوه استفاده از add_filter، و استفاده درست از هوک‌ها.

سه نکته در استفاده صحیح: یک — callback نام‌دار بگذارید: استفاده از تابع ناشناس (closure) امکان حذف بعدی هوک را از بین می‌برد. اگر ممکن است کسی بعداً بخواهد این هوک را حذف کند، از callback نام‌دار استفاده کنید. دو — پیشوند یکتا: نام تابع callback باید پیشوند اختصاصی داشته باشد. سه — متد کلاس به‌جای تابع سراسری: در افزونه‌های حرفه‌ای، callback یک متد کلاس است، نه تابع سراسری. الگوهای مشابه در ساختار فایل‌های افزونه استاندارد و توسعه افزونه از صفر آمده است.

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

اولویت (Priority): ترتیب اجرا

پارامتر سوم add_action و add_filter، priority است. پیش‌فرض ۱۰ است و هرچه کمتر باشد، تابع زودتر اجرا می‌شود. اهمیت این پارامتر در سه سناریو:

  • اتصال به هوک‌های اولیه: برای هوک‌هایی مثل plugins_loaded یا after_setup_theme، ممکن است نیاز به اولویت پایین‌تر باشد تا کد شما قبل از افزونه‌های دیگر اجرا شود.
  • اجرای callback بعد از callback افزونه دیگر: اگر می‌خواهید فیلتر شما بعد از یک افزونه خاص اجرا شود، priority بالاتری از آن بدهید (مثلاً ۲۰ یا ۳۰). این کار در پروژه‌هایی که افزونه‌ای روی فیلتر the_content قرار دارد، بسیار کاربردی است.
  • بازنویسی رفتار پیش‌فرض: اگر می‌خواهید رفتار یک هوک پیش‌فرض را قبل از اجرای آن تغییر دهید، از priority پایین‌تر استفاده کنید.

یک نکته مهم که در پروژه‌های تیمی زیاد دیده‌ام: نبود مستندسازی priority در کد. اگر priority شما ۲۰ یا ۳۰ است، دلیلش را در کامنت بنویسید. سه ماه بعد، خودتان هم نمی‌دانید چرا ۲۰ گذاشته‌اید. این یک نمونه ساده از اصول کدنویسی تمیز در سطح جزئیات است. راهنمای کامل priority در priority در هوک‌های وردپرس، کنترل ترتیب اجرای هوک‌ها، و راهنمای حرفه‌ای هوک‌ها آمده است.

حذف هوک‌ها به روش درست

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

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

remove_action( 'wp_footer', 'myplugin_add_footer_signature', 10 );

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

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

ساخت هوک سفارشی

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

// ساخت اکشن سفارشی
do_action( 'myplugin_after_order_created', $order_id, $user_id );

// استفاده از اکشن سفارشی
add_action( 'myplugin_after_order_created', 'myplugin_send_notification', 10, 2 );

// ساخت فیلتر سفارشی
$final_price = apply_filters( 'myplugin_final_price', $base_price, $user_id );

// استفاده از فیلتر سفارشی
add_filter( 'myplugin_final_price', 'myplugin_apply_discount', 10, 2 );

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

هوک در قالب در برابر افزونه

یکی از پرتکرارترین سؤالات در پروژه‌ها: هوک را در قالب بنویسم یا افزونه؟ سه سناریو:

  • هوک‌های ظاهری: اگر هوک فقط روی نمایش اثر دارد (مثلاً افزودن یک بخش به فوتر یا تغییر عنوان)، می‌تواند در چایلد تم باشد. مثال: wp_footer، the_content، excerpt_length. راهنما در هوک‌های قالب و هوک‌های خروجی قالب.
  • هوک‌های منطقی: اگر هوک منطق کسب‌وکار دارد (ثبت نوع‌نوشته، ذخیره داده، ارسال ایمیل)، باید در افزونه باشد. اگر این هوک‌ها در قالب باشند، روز تغییر قالب، منطق از دست می‌رود. راهنما در هوک‌های افزونه و مراحل ساخت افزونه اختصاصی.
  • هوک‌های ساختاری: هوک‌هایی که ساختار قالب را تعریف می‌کنند (after_setup_theme، widgets_init) در چایلد تم قرار می‌گیرند. راهنما در چایلد تم و ساختار فایل‌های قالب استاندارد.

یک قاعده عملی در پروژه‌های خودم: ۸۰٪ هوک‌ها در افزونه، ۲۰٪ در چایلد تم. اگر در پروژه‌ای نسبت برعکس شد، احتمالاً منطق کسب‌وکار در قالب نشسته که در روز تغییر قالب به بحران تبدیل می‌شود.

هوک‌هایی که در قالب زندگی می‌کنند، عمری به عمر قالب دارند؛ هوک‌هایی که در افزونه زندگی می‌کنند، عمری به عمر کسب‌وکار.

دیباگ هوک‌ها: ابزارها و روش‌ها

وقتی هوکی کار نمی‌کند یا تعارض ایجاد می‌کند، سه ابزار در پروژه‌های خودم استفاده می‌کنم:

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

هوک‌های پرکاربرد در پروژه‌های واقعی

فهرست کوتاه از هوک‌هایی که در ۹۰٪ پروژه‌ها به‌کار می‌برم، به تفکیک حوزه:

حوزههوککاربرد
راه‌اندازیinitثبت post type، تاکسونومی، شورت‌کد
قالبafter_setup_themeadd_theme_support، register_nav_menus
assetwp_enqueue_scriptsenqueue CSS/JS در front-end
پیشخوانadmin_menuثبت منو در پیشخوان
محتواthe_contentفیلتر محتوای نوشته
ذخیرهsave_postذخیره داده پس از انتشار نوشته
کاربرuser_registerپس از ثبت‌نام کاربر جدید
ورودwp_loginپس از ورود کاربر
فروشگاهwoocommerce_thankyouپس از اتمام سفارش

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

اشتباهات رایج در استفاده از هوک‌ها

  • انتخاب هوک اشتباه: ثبت نوع‌نوشته روی after_setup_theme به‌جای init. این اشتباه، در نیمی از پروژه‌های تازه‌کار دیده‌ام. راهنما در هوک‌های وردپرس.
  • نبود return در فیلتر: callback فیلتر با echo به‌جای return. تغییر اعمال نمی‌شود. راهنما در نحوه استفاده از add_filter.
  • priority بدون دلیل: عوض کردن priority بدون درک دلیل. اگر نمی‌دانید چرا ۲۰ گذاشته‌اید، احتمالاً نیازی نیست. راهنما در priority در هوک‌ها.
  • حذف هوک با priority اشتباه: remove_action با priority متفاوت از add_action حذف نمی‌کند. راهنما در حذف اکشن هوک.
  • استفاده از closure در هوک‌هایی که باید حذف شوند: closure قابل حذف نیست. راهنما در استفاده درست از هوک‌ها.
  • نبود مستندسازی هوک سفارشی: سه ماه بعد، کسی نمی‌داند هوک شما چه پارامترهایی می‌گیرد. راهنما در ساختار استاندارد کدنویسی.
  • فراموش کردن do_action یا apply_filters در پروژه‌های تیمی: اگر دو توسعه‌دهنده روی یک بخش کار می‌کنند و یکی هوک سفارشی ثبت می‌کند ولی دیگری نمی‌داند، کد دوم اجرا نمی‌شود. راهنما در ساختاربندی پروژه وردپرس.
  • نادیده‌گرفتن accepted_args: اگر فیلتر سه پارامتر دارد و شما یک پارامتر اعلام کنید، فقط پارامتر اول را می‌بینید. راهنما در پارامترهای هوک.
  • فراخوانی توابع شرطی در هوک اشتباه: is_singular در init کار نمی‌کند. راهنما در هوک‌های وردپرس.
  • نبود پیشوند یکتا در نام هوک سفارشی: تعارض با هوک‌های دیگر. راهنما در اشتباهات رایج هوک.
  • نادیده‌گرفتن ترتیب bootstrap افزونه‌ها: هوک شما قبل از اینکه کد شما لود شود، اجرا می‌شود. راهنما در کنترل ترتیب اجرای هوک‌ها.
  • نبود تست روی محیط استیجینگ: تعارض هوک‌ها روی سایت زنده کشف می‌شود. راهنما در بهترین روش تست وردپرس.

الگوی حرفه‌ای: Registry Pattern برای هوک‌ها

در پروژه‌های بزرگ، ثبت هوک‌ها را در یک نقطه واحد انجام دهید، نه پراکنده در فایل‌های مختلف. الگوی ساده:

class My_Plugin_Hooks {
    public static function init() {
        add_action( 'init', array( __CLASS__, 'register_post_type' ) );
        add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_assets' ) );
        add_filter( 'the_content', array( __CLASS__, 'modify_content' ) );
        add_action( 'save_post', array( __CLASS__, 'save_data' ), 10, 3 );
    }

    public static function register_post_type() {
        // ثبت post type
    }

    public static function enqueue_assets() {
        // enqueue
    }

    public static function modify_content( $content ) {
        return $content;
    }

    public static function save_data( $post_id, $post, $update ) {
        // ذخیره داده
    }
}
My_Plugin_Hooks::init();

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

جمع‌بندی

هوک‌های وردپرس، در چهار اصل خلاصه می‌شوند: انتخاب اکشن یا فیلتر بر اساس ماهیت کار، استفاده از callback نام‌دار با پیشوند یکتا، مدیریت priority با دلیل و مستندسازی، و قرار دادن هوک در لایه درست (افزونه برای منطق، چایلد تم برای ظاهر). سه اصل را در پایان تاکید می‌کنم: اول، هوک را به‌عنوان پایه معماری ببینید، نه قابلیت جانبی. دوم، priority را با دلیل عوض کنید و دلیلش را در کامنت بنویسید. سوم، از closure در هوک‌هایی که ممکن است بعداً حذف شوند، پرهیز کنید.

اگر امروز یک کار در این مسیر انجام می‌دهید: در پروژه فعلی خود، فایل‌های قالب و افزونه را باز کنید و ببینید آیا هوکی هست که در لایه اشتباه قرار گرفته — مثلاً منطق در قالب، یا نمایش در افزونه. همان یک بازبینی، در روز تغییر قالب یا آپدیت، نجات‌دهنده است. اگر تجربه‌ای از یک تعارض هوک یا یک الگوی موفق در پروژه‌ای دارید، در دیدگاه‌ها بنویسید — همان گزارش‌های واقعی، این راهنما را برای توسعه‌دهنده بعدی دقیق‌تر می‌کند. 🔗