هوکهای وردپرس چیستند و چگونه کار میکنند
راهنمای عمیق و عملی هوکهای وردپرس؛ از اکشن و فیلتر و چرخه اجرا تا اولویت، حذف، هوک سفارشی و اشتباهات رایج بر پایه تجربه پروژههای واقعی.
آن روزی که فهمیدم هوک، ستون فقرات وردپرس است
اولین قالب اختصاصی که نوشتم، یک قالب ساده برای یک وبلاگ شخصی بود. همهچیز کار میکرد تا روزی که صاحب سایت خواست متن فوتر را تغییر دهد. من مستقیم رفتم سراغ 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) در چایلد تم قرار میگیرند. راهنما در چایلد تم و ساختار فایلهای قالب استاندارد.
یک قاعده عملی در پروژههای خودم: ۸۰٪ هوکها در افزونه، ۲۰٪ در چایلد تم. اگر در پروژهای نسبت برعکس شد، احتمالاً منطق کسبوکار در قالب نشسته که در روز تغییر قالب به بحران تبدیل میشود.
هوکهایی که در قالب زندگی میکنند، عمری به عمر قالب دارند؛ هوکهایی که در افزونه زندگی میکنند، عمری به عمر کسبوکار.
دیباگ هوکها: ابزارها و روشها
وقتی هوکی کار نمیکند یا تعارض ایجاد میکند، سه ابزار در پروژههای خودم استفاده میکنم:
- افزونه Query Monitor: تمام هوکهای اجرا شده در هر صفحه را نشان میدهد، با ترتیب، priority و callbackها. این ابزار، اولین قدم در تشخیص تعارض بین دو افزونه روی یک هوک است. راهنما در توابع دیباگ وردپرس.
- error_log و WP_DEBUG: در هوک مشکوک،
error_log( 'reached' )بگذارید تا ببینید کد اجرا میشود یا نه. مسیر کامل در دیباگ کد سفارشی وردپرس و تست و دیباگ پروژههای وردپرس. - حذف دستهای هوکها: اگر تعارض بین دو افزونه است، یکی را غیرفعال کنید و ببینید مشکل حل میشود یا نه. مسیر کامل در شناسایی افزونه مشکلساز و بررسی سازگاری قالب و افزونه.
یک نکته تخصصی: در پروژههای بزرگ که چند افزونه روی یک هوک کار میکنند، ترتیب priority در دیباگ حیاتی است. اگرچه Query Monitor این ترتیب را نشان میدهد، درک چرایی آن ترتیب، تفاوت بین دیباگ سریع و دیباگ کند است. مسیر مشابه در دیباگ اکشن و فیلتر آمده است.
هوکهای پرکاربرد در پروژههای واقعی
فهرست کوتاه از هوکهایی که در ۹۰٪ پروژهها بهکار میبرم، به تفکیک حوزه:
| حوزه | هوک | کاربرد |
|---|---|---|
| راهاندازی | init | ثبت post type، تاکسونومی، شورتکد |
| قالب | after_setup_theme | add_theme_support، register_nav_menus |
| asset | wp_enqueue_scripts | enqueue 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 در هوکهایی که ممکن است بعداً حذف شوند، پرهیز کنید.
اگر امروز یک کار در این مسیر انجام میدهید: در پروژه فعلی خود، فایلهای قالب و افزونه را باز کنید و ببینید آیا هوکی هست که در لایه اشتباه قرار گرفته — مثلاً منطق در قالب، یا نمایش در افزونه. همان یک بازبینی، در روز تغییر قالب یا آپدیت، نجاتدهنده است. اگر تجربهای از یک تعارض هوک یا یک الگوی موفق در پروژهای دارید، در دیدگاهها بنویسید — همان گزارشهای واقعی، این راهنما را برای توسعهدهنده بعدی دقیقتر میکند. 🔗