چگونه پارامترهای هوک وردپرس را بشناسیم
پارامترهای هوک وردپرس را چطور بشناسیم؟ راهنمای عملی خواندن امضای هوک، معنی پارامتر چهارم add_action، رفتار filter با آرگومانهای اضافی، و روشهای کشف
یکی از پرتکرارترین سؤالاتی که در جلسات دیباگ با توسعهدهندگان میشنوم این است: «چرا تابع من اصلاً اجرا نمیشود؟» و بعد از بررسی، تقریباً همیشه جواب یک چیز است: تعداد آرگومانهای اشتباه. توسعهدهنده یک add_filter نوشته، ولی پارامتر چهارم را روی مقدار پیشفرض گذاشته، یا در سمت callback انتظار سه ورودی دارد و در واقع دو ورودی میرسد. مشکل نه در منطق کد است و نه در انتخاب هوک؛ مسئله در فهم نادرست از پارامترهای هوک وردپرس است. اگر شما هم در پروژهای به این دام افتادهاید، این مقاله دقیقاً برای همین نوشته شده. اگر با مفهوم پایهٔ هوک آشنایی ندارید، پیش از ادامه هوکهای وردپرس چیستند و چگونه کار میکنند را بخوانید، و اگر با نحوۀ افزودن هوک دستوپنجه نرم میکنید، نحوه استفاده از add_action در وردپرس و نحوه استفاده از add_filter در وردپرس نقطهٔ شروع خوبی است.
چرا پارامترهای هوک، پاشنهٔ آشیل توسعهدهندههای وردپرس است
در معماری وردپرس، هر هوک یک «قرارداد» است: هسته یا افزونهای اعلام میکند که این هوک را با این تعداد و این نوع پارامتر اجرا میکند. کد شما، بهعنوان شنوندهٔ این هوک، موظف است با این قرارداد همسویی کند. اگر callback شما انتظار سه پارامتر داشته باشد ولی هوک دو پارامتر بفرستد، پارامتر سوم مقدار پیشفرض PHP را میگیرد (یا خطا میدهد)، و منطق شما بیسروصدا از کار میافتد.
سه دلیل این مسئله را به یکی از پرهزینهترین دامهای توسعهٔ وردپرس تبدیل میکند:
اول، خطا گزارش نمیشود. PHP بهطور پیشفرض وقتی callback پارامتر کمتری بگیرد، هیچ هشداری نمیدهد؛ فقط آن پارامتر مقدار null میگیرد و تابع شما احتمالاً بهجای خطا، نتیجهٔ نادرست میسازد. کشف این نوع باگ، گاهی ساعتها وقت میگیرد.
دوم، مستندات همیشه کامل نیست. در مستندات رسمی وردپرس، پارامترهای هر هوک فهرست شدهاند؛ ولی در هوکهای سفارشی افزونههای دیگر، این مستندات گاهی ناقص یا قدیمی است. توسعهدهنده باید بتواند پارامترها را از دل کد خودش کشف کند.
سوم، تغییر پارامترها در نسخههای بعدی. برخی افزونهها در آپدیتها، تعداد پارامترهای یک هوک را تغییر میدهند (معمولاً اضافه میکنند). اگر کد شما به تعداد دقیق پارامترها وابسته باشد، بعد از آپدیت ممکن است بشکند.
پارامترهای هوک، پل ارتباطی بین «کسی که هوک را صدا میزند» و «کسی که به آن گوش میدهد» است. اگر این پل یکطرفه ساخته شود، پیام هیچوقت به مقصد نمیرسد.
امضای هوک: نام، callback، اولویت و تعداد آرگومان
هر فراخوانی add_action یا add_filter چهار بخش دارد که در مجموع «امضای هوک» را میسازند:
add_action(
'init', // 1. نام هوک
'wphk_custom_init', // 2. نام callback
10, // 3. اولویت
2 // 4. تعداد آرگومانهای دریافتی
);
سه بخش اول برای اکثر توسعهدهندگان شناختهشده است؛ نام هوک، تابع callback و اولویت. مشکل، تقریباً همیشه در بخش چهارم است: تعداد آرگومانهایی که callback دریافت میکند. مقدار پیشفرض این پارامتر ۱ است؛ یعنی اگر آن را ننویسید، callback شما فقط یک آرگومان میگیرد، حتی اگر هوک واقعاً چند آرگومان بفرستد. این تفاوت ظریف، منبع بیپایان باگهای «چرا چیزی که باید کار کند، کار نمیکند» است.
نکتهٔ کلیدی این است که «تعداد آرگومانها در سمت هوک» و «تعداد آرگومانها در سمت callback» دو چیز جدا هستند. هوک ممکن است پنج پارامتر داشته باشد؛ ولی اگر شما پارامتر چهارم را روی ۲ بگذارید، callback شما فقط دو تای اول را دریافت میکند. این طراحی، عمدی است؛ وردپرس میخواهد از بارگذاری دادههای اضافی در حافظه جلوگیری کند. اما اگر توسعهدهنده این طراحی را نشناسد، تصور میکند هوک فقط دو پارامتر دارد.
پارامتر چهارم add_action و add_filter چیست
پارامتر چهارم در این دو تابع، $accepted_args نام دارد و نقش آن این است: مشخص میکند callback شما چند آرگومان از هوک دریافت کند. سه حالت ممکن است پیش بیاید:
حالت اول: مقدار پیشفرض (۱)
اگر پارامتر چهارم را ندهید، callback شما فقط یک آرگومان میگیرد. این برای اکثر هوکهای ساده کافی است، ولی برای هوکهایی مثل save_post یا the_content که چند پارامتر دارند، کافی نیست.
// فقط یک آرگومان دریافت میشود
add_action( 'save_post', 'wphk_save_post_one_arg' );
function wphk_save_post_one_arg( $post_id ) {
// فقط $post_id در دسترس است
}
حالت دوم: مقدار صریح بزرگتر از ۱
وقتی میدانید هوک چند پارامتر دارد و به بیشتر از یکی نیاز دارید، عدد صریح انتخاب کنید:
// سه آرگومان دریافت میشود
add_action( 'save_post', 'wphk_save_post_three_args', 10, 3 );
function wphk_save_post_three_args( $post_id, $post, $update ) {
if ( $update ) {
// منطق مربوط به بهروزرسانی
}
}
حالت سوم: عددی بزرگتر از تعداد واقعی پارامترهای هوک
اگر عددی بزرگتر از پارامترهای واقعی هوک بدهید، وردپرس بدون خطا آن را نادیده میگیرد و فقط پارامترهای موجود را پاس میدهد. مثال: اگر هوک دو پارامتر داشته باشد و شما ۵ بگذارید، callback شما همان دو پارامتر را در دو ورودی اول میگیرد و بقیه، مقدار پیشفرض PHP (null) میگیرند. این رفتار باعث میشود توسعهدهنده فکر کند هوک پنج پارامتر دارد، درحالیکه واقعاً دو پارامتر میفرستد.
پارامتر چهارم، یک تنظیم حاشیهای نیست؛ زبانی است که با آن به وردپرس میگویید «چقدر از دادهات را میخواهم ببینم». اگر این عدد را درست ندهید، دادهای که میخواهید هرگز نمیرسد.
تفاوت پارامتری Action و Filter
در نگاه اول، تفاوت پارامتری add_action و add_filter شبیه هم است؛ ولی در سطح منطق، دو تفاوت کلیدی وجود دارد که باید بشناسید:
اولین تفاوت: بازگشت مقدار در Filter
در Filter، callback شما موظف است مقدار پارامتر اول را برگرداند. اگر آن را برنگردانید، خروجی سایت به null تبدیل میشود. در Action، این تعهد وجود ندارد؛ چون Action قصد بازگشت مقدار ندارد. این تفاوت در تابعهای ساده دیده نمیشود، ولی وقتی با آرگومانهای اضافی کار میکنید، اهمیتش بیشتر میشود.
// Filter: باید مقدار برگردد
add_filter( 'the_content', 'wphk_modify_content', 10, 1 );
function wphk_modify_content( $content ) {
return $content . '<p>متن اضافه</p>';
}
دومین تفاوت: محل قرارگیری پارامترها
در Action، هر آرگومانی که هسته یا افزونهٔ میزبان پاس میدهد، مستقیماً به callback شما میرسد. در Filter، پارامتر اول همیشه همان مقداری است که باید بازگردانده شود. بنابراین اگر هوکی مثل the_content واقعاً دو پارامتر بفرستد (محتوا + شیء پست)، پارامتر اول همیشه محتوا است و پارامتر دوم، دادهٔ اضافه.
برای درک دقیقتر این تفاوت، تفاوت Action و Filter در وردپرس چیست را ببینید. فهم این تفکیک در طراحی callbackها، شما را از بسیاری از باگهای ظریف نجات میدهد.
چگونه پارامترهای یک هوک را کشف کنیم
پرتکرارترین سناریو این است که میخواهید به یک هوک سفارشی (از یک افزونهٔ ناشناخته یا قالب دیگر) متصل شوید و نمیدانید این هوک چند پارامتر میفرستد. سه روش عملی که در پروژههای خودم بهکار میبرم:
روش اول: جستجو در کد منبع افزونه یا قالب
سادهترین راه این است که در پوشهٔ افزونه یا قالب، دنبال نام هوک بگردید. بیشتر هوکها با توابع do_action یا apply_filters اجرا میشوند و پارامترها در همان خط مشخصاند:
// در کد افزونه:
do_action( 'wphk_before_checkout_render', $cart, $user, $options );
// شما میدانید که این هوک سه پارامتر میفرستد:
// $cart, $user, $options
اگر از ابزار جستجوی کد در VS Code یا از خط فرمان grep استفاده کنید، در چند ثانیه پیدا میشود:
grep -rn "do_action( 'wphk_before_checkout_render'" wp-content/plugins/
روش دوم: افزونهٔ Query Monitor
این افزونه، در هر اجرای صفحه، فهرست تمام هوکهای فعال را با hook handlerهایشان نشان میدهد. اگر روی هر هوک کلیک کنید، میتوانید ببینید چند callback به آن متصل است و با چه اولویتی. این ابزار برای کشف سریع پارامترهای یک هوک مفید است، چون تعداد callbackها و امضایشان را یکجا میبینید.
روش سوم: یک callback آزمایشی با تعداد آرگومان بالا
در مواردی که به کد منبع دسترسی ندارید (مثلاً افزونهای رمزگذاریشده یا با loader پیچیده)، میتوانید یک callback آزمایشی با تعداد آرگومان بالا ثبت کنید و آنها را لاگ بگیرید:
add_action( 'wphk_unknown_hook', 'wphk_probe_hook', 10, 10 );
function wphk_probe_hook() {
$args = func_get_args();
error_log( 'Probe: ' . print_r( $args, true ) );
}
با این کد، در فایل لاگ PHP میبینید که واقعاً چند آرگومان با چه مقادیری پاس شده است. نکتهٔ ظریف: استفاده از func_get_args() بهجای تعریف پارامترهای صریح، به شما اجازه میدهد بدون دانستن تعداد دقیق، همه را بگیرید. این الگو در موقعیتهای کشف پارامتر، ابزار کارآمدی است.
روش دقیقتر این کشف و ابزارهای تکمیلی در دیباگ کردن Action و Filter در وردپرس آمده است. یک تذکر: هیچگاه این لاگ را در محیط تولیدی رها نکنید؛ فقط برای کشف موقت از آن استفاده کنید.
سمت callback: تعریف درست ورودیها
پس از کشف پارامترها، نوبت به تعریف امضای callback میرسد. سه نکتهٔ عملی که در پروژههای خودم رعایت میکنم:
نکتهٔ اول: نامگذاری معنادار
بهجای $a، $b، $c، از نامهای معنادار استفاده کنید. اگر پارامتر اول محتواست، $content؛ اگر شیء پست است، $post. این کار نهفقط خوانایی را بالا میبرد، بلکه در زمان دیباگ هم سریعتر به ذهن میآید که هر پارامتر چیست.
نکتهٔ دوم: تعریف دقیق تعداد آرگومانها در دو سمت
تعداد پارامترهای callback و تعداد آرگومانهای پارامتر چهارم add_action باید هماهنگ باشند. اگر callback شما سه پارامتر میگیرد ولی پارامتر چهارم را ۱ گذاشتهاید، دو پارامتر دیگر مقدار null میگیرند و منطق شما بیسروصدا شکست میخورد:
// نادرست: callback سه پارامتر میگیرد، ولی فقط یک آرگومان پاس میشود
add_action( 'save_post', 'wphk_wrong_example' ); // پیشفرض: 1
function wphk_wrong_example( $post_id, $post, $update ) {
// $post و $update همیشه null هستند
}
// درست:
add_action( 'save_post', 'wphk_right_example', 10, 3 );
function wphk_right_example( $post_id, $post, $update ) {
// هر سه پارامتر معتبرند
}
نکتهٔ سوم: بررسی نوع داده پیش از استفاده
پارامترها همیشه با نوع دادهٔ مورد انتظار نمیرسند. مثلاً در برخی نسخهها، پارامتر اول ممکن است بهجای عدد، رشته باشد یا یک شیء خاص. عادت به بررسی نوع، شما را از خطاهای پنهان نجات میدهد:
function wphk_safe_callback( $post_id, $post, $update ) {
if ( ! $post instanceof WP_Post ) {
return;
}
// منطق با فرض $post معتبر
}
الگوی مشابهی از این نوع بررسی در کد قالبها و افزونههای حرفهای بهکار میرود، مثلاً در بحث محتوای نوشتهها در نحوه حذف یک Filter Hook در وردپرس که میبینید چگونه بررسی نوع، بخشی از کد امن است.
پارامترها در هوکهای سفارشی خودتان
وقتی شما خودتان یک هوک سفارشی تعریف میکنید، میتوانید هر تعداد پارامتر به آن بدهید. این آزادی، مسئولیت هم میآورد. سه تصمیم کلیدی در طراحی هوک سفارشی:
تصمیم اول: چند پارامتر پاس دهیم؟
قاعدهٔ عمومی: کمترین تعداد لازم. هر پارامتر اضافه، بار حافظه و پیچیدگی امضای callback را بالا میبرد. اگر دادهٔ اضافه در دسترس است ولی کسی به آن نیاز ندارد، پاسدادنش بیفایده است. در هوکهای عمومی که ممکن است توسعهدهندههای دیگر از آنها استفاده کنند، تعداد کم پارامتر باعث میشود کد خواناتر بماند.
تصمیم دوم: چه ترتیبی برای پارامترها انتخاب کنیم؟
ترتیب پارامترها بخشی از قرارداد عمومی هوک شماست. اگر بعداً ترتیب را عوض کنید، کدهای موجود میشکنند. الگوی پیشنهادی: پارامتر اول همیشه مهمترین دادهٔ زمینه (context) باشد؛ پارامترهای بعدی، دادهٔ کمکی. مثال در یک هوک سفارشی:
/**
* اجرا پیش از رندر کادر محصولات مرتبط.
*
* @param int $product_id شناسهٔ محصول جاری
* @param array $related فهرست محصولات مرتبط
* @param array $settings تنظیمات نمایش کادر
*/
do_action( 'wphk_before_related_box', $product_id, $related, $settings );
تصمیم سوم: مستندسازی پارامترها
هر هوک سفارشی که در اختیار دیگران میگذارید، باید با یک docblock همراه باشد که نام، نوع و معنی هر پارامتر را توضیح میدهد. این مستندسازی، تفاوت بین یک افزونهٔ حرفهای و یک افزونهٔ آماتور است. نمونهٔ ساختار docblock:
/**
* Fires before rendering the custom notice box.
*
* @since 1.0.0
*
* @param string $context محل نمایش کادر (single|archive)
* @param WP_Post $post شیء پست مربوطه
* @param array $options تنظیمات کادر
*/
do_action( 'wphk_before_notice_box', $context, $post, $options );
الگوی کامل ساخت هوک سفارشی با پارامترها در چگونه یک Action سفارشی در وردپرس بسازیم و چگونه یک Filter سفارشی در وردپرس بسازیم آمده است.
استفاده از ... و پارامترهای variadic
در PHP ۵.۶ و بالاتر، از syntax «variadic» پشتیبانی میشود که به شما اجازه میدهد callback را با تعداد نامعلومی پارامتر تعریف کنید:
add_action( 'wphk_unknown_hook', 'wphk_variadic_callback', 10, 10 );
function wphk_variadic_callback( ...$args ) {
// $args یک آرایه است که همهٔ پارامترها را دارد
$count = count( $args );
error_log( sprintf( 'Received %d arguments', $count ) );
}
این الگو در سه سناریو مفید است: کشف پارامترها، هوکهایی که تعداد پارامترهایشان در نسخههای مختلف تغییر میکند، و هوکهای عمومی که ممکن است سایر توسعهدهندهها به آن پارامتر اضافه کنند. یک هشدار: syntax variadic با PHP قدیمیتر از ۵.۶ سازگار نیست. اگر افزونه شما باید روی PHP 5.4 کار کند (که امروز نادر است، ولی در برخی هاستهای قدیمی ایران ممکن است)، باید از func_get_args() استفاده کنید:
function wphk_compat_callback() {
$args = func_get_args();
// $args آرایهای از تمام پارامترها
}
دیباگ پارامترها در پروژههای واقعی
وقتی با مشکلی روبهرو میشوید که بهنظر میرسد پارامترها درست پاس نمیشوند، روش من در پروژهها سه مرحله دارد:
مرحلهٔ اول، شمارش آرگومانهای ورودی: در ابتدای callback، با func_num_args() تعداد آرگومانهای واقعی را ثبت میکنم:
function wphk_debug_args( $arg1 = null, $arg2 = null, $arg3 = null ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
$count = func_num_args();
error_log( sprintf( 'wphk: callback received %d args', $count ) );
}
// منطق اصلی
}
مرحلهٔ دوم، بررسی نوع و مقدار: هر پارامتر را با error_log ثبت میکنم تا مطمئن شوم دادهها معنادار هستند:
function wphk_debug_values( $post_id, $post = null, $update = null ) {
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
error_log( sprintf(
'wphk: post_id=%s, post_type=%s, update=%s',
var_export( $post_id, true ),
is_object( $post ) ? get_class( $post ) : gettype( $post ),
var_export( $update, true )
) );
}
}
مرحلهٔ سوم، بررسی تعداد اعلامشده در add_action: این عدد را در کد callback یا در کنار add_action بازبینی میکنم. اگر callback من ۳ پارامتر میگیرد و add_action پارامتر چهارم را ۱ گذاشته، این ناهماهنگی، مقصر است.
الگوی مشابه دیباگ و ابزارهای مرتبط در دیباگ کردن Action و Filter در وردپرس آمده است.
اشتباهات رایج دربارهٔ پارامترهای هوک
در بازبینی دهها افزونه و چایلد تم، این شش الگو بیشترین تکرار را داشتهاند:
| اشتباه | پیامد واقعی | اصلاح |
|---|---|---|
نبود پارامتر چهارم در add_action | callback فقط یک آرگومان میگیرد؛ بقیه null | تعیین صریح تعداد آرگومانها |
| ناهماهنگی تعداد در دو سمت | پارامترهای خالی و منطق ناقص | بررسی هر دو سمت پیش از انتشار |
| نبود بررسی نوع داده در callback | خطای fatal در برخی شرایط | بررسی instanceof و is_* |
فراموشی return در Filter | محتوای سایت null میشود | همیشه مقدار ورودی را برگردانید |
| استفاده از نامهای بیمعنا ($a, $b) | دیباگ کند و خطاپذیر | نامگذاری معنادار براساس نقش |
| نبود مستندسازی پارامترها در هوک سفارشی | توسعهدهندهٔ بعدی نمیداند چطور متصل شود | docblock کامل با @param |
هر کدام از این موارد را در پروژهای دیدهام و هزینهاش را یا مشتری پرداخته یا توسعهدهندهٔ بعدی. شرح مفصلتر اشتباهات مشترک هوکها در اشتباهات رایج هنگام استفاده از هوکها آمده است.
نگاه معمارانه به پارامترها و قرارداد پایداری
پارامترهای هوک، از منظر معماری نرمافزار، یک «قرارداد» بین دو طرف هستند و این قرارداد، بخشی از رابط عمومی هر افزونه یا قالب است. سه اصل که در طراحی و مصرف پارامترها در پروژههای جدی بهکارم آمده:
اصل اول: پایداری قرارداد. اگر افزونهٔ شما هوکی تعریف کرد، ترتیب و نوع پارامترهایش بخشی از قرارداد عمومی است. تغییر آن در آپدیتهای بعدی، کدهای مصرفکننده را میشکند. اگر مجبور به تغییر هستید، راه درست این است که هوک جدید با نام متفاوت بسازید و بهآرامی نسخهٔ قدیمی را deprecate کنید. الگوی مشابه این کار در بحث مدیریت ترتیب اجرای هوکها هم بهعنوان یک درس معماری مطرح شده است.
اصل دوم: حداقل دادهی ضروری. پاسدادن شیء بزرگ یا دادهای که مصرفکننده به آن نیازی ندارد، بار حافظه و پیچیدگی را بالا میبرد. در طراحی هوک سفارشی، فقط دادهای که در قرارداد تعریف کردهاید پاس دهید و اگر دادهٔ اضافه لازم شد، از توابع دسترسی (getter) استفاده کنید. این اصل، در سایتهای پربازدید که هر هوک در هر درخواست اجرا میشود، اثر جدی روی سرعت دارد؛ مبحث کامل در افزونههای وردپرس چگونه روی سرعت سایت اثر میگذارند آمده است.
اصل سوم: عدم اتکا به پارامترهای پنهان. اگر کد شما به پارامتری وابسته است که در مستندات نیست، این وابستگی، شکننده است. توسعهدهندهٔ افزونهٔ میزبان میتواند در آپدیت بعدی، آن پارامتر را بدون اعلام حذف کند. بهترین راه، بررسی مستندات رسمی و نوشتن callback با فرض اینکه فقط پارامترهای اعلامشده در دسترس هستند.
و یک توصیهٔ عملی از تجربهٔ پروژههای تیمی: هر هوک سفارشی که در افزونهٔ اختصاصی خود تعریف میکنید، در یک فایل مستندات جدا ثبت کنید. این فایل، برای توسعهدهندههای بعدی، نقشهٔ راه درست برای اتصال به هوکهای شما میشود. اگر با ساختار معماری توسعهٔ افزونه آشنا نیستید، هوکهای وردپرس در توسعه افزونه چه کاربردی دارند و راهنمای حرفهای کار با هوکهای وردپرس مراجع کاملتری هستند.
هر پارامتر هوک، یک کلمه از یک جملهٔ طولانی است. اگر یک کلمه گم شود یا در جای اشتباه بیفتد، معنای کل جمله عوض میشود. برای فهم پارامترها، باید جمله را کامل بشناسید، نه فقط کلمات جداگانه را.
جمعبندی و گام بعدی عملی
پارامترهای هوک وردپرس، از منظر سطحی، چهار جزئیات ساده بهنظر میرسند؛ ولی در سطح عملی، تعیینکنندهٔ رفتار هر hook handler هستند. مهمترین نکات این مقاله: پارامتر چهارم add_action و add_filter تعداد آرگومانهای callback را تعیین میکند؛ نبود این عدد باعث میشود callback فقط یک آرگومان بگیرد؛ ناهماهنگی تعداد در دو سمت، منبع باگهای پنهان است؛ در Filter، بازگشت مقدار پارامتر اول الزامی است؛ و در هوکهای سفارشی، ترتیب و نوع پارامترها بخشی از قرارداد عمومی است و باید مستند شود.
گام بعدی عملی که پیشنهاد میکنم: در همین امروز، فایل functions.php چایلد تم یا افزونهٔ خود را باز کنید و ببینید چند add_action یا add_filter بدون پارامتر چهارم نوشتهاید. برای هرکدام که callback بیش از یک پارامتر میگیرد، پارامتر چهارم را صریح تعیین کنید و در کنارش یک کامنت کوتاه بنویسید که چرا این تعداد. این تمرین یکساعته، آگاهی شما را از رفتار هوکها بالا میبرد و در پروژهٔ بعدی، ساعتها وقت دیباگ ذخیره میکند. اگر در پروژهای با تعارض پارامتری روبهرو شدهاید و روش جالبی برای کشف یا حل آن پیدا کردهاید، برای من جالب است بدانید کدام هوک بود و چگونه پارامترها را کشف کردید — تجربهٔ خودتان را در دیدگاهها بنویسید؛ بهویژه اگر روشی پیدا کردهاید که بدون جستجو در کد افزونه، پارامترهای هوکهای ناشناخته را بهسادگی کشف میکند. 🧭