تابع do_shortcode() در وردپرس ابزار رسمی پردازش و اجرای شورتکدها در متن است و به‌عنوان یکی از پرکاربردترین توابع پردازش محتوا، امکان استفاده از شورتکد در فیلدهای سفارشی، ویجت‌ها و قالب‌ها را فراهم می‌کند. بدون این تابع، وردپرس فقط شورتکدهای موجود در محتوای نوشته را پردازش می‌کند و بقیه نقاط سایت از این امکان محروم می‌مانند.

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

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

چرا do_shortcode اهمیت دارد

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

  • فیلدهای سفارشی (Custom Fields)
  • متن ویجت‌ها
  • توضیحات برگه‌ها
  • محتوای Termها
  • گزینه‌های پنل تنظیمات

در همه این موارد، اگر بخواهید شورتکد را اجرا کنید، باید خودتان do_shortcode را فراخوانی کنید. برای درک کامل چرخه پردازش، مطالب تابع add_shortcode را مطالعه کنید.

ساختار و امضای تابع do_shortcode

امضای این تابع به شکل زیر است:

do_shortcode( string $content, bool $ignore_html = false ): string

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

$text = 'محتوای من [myplugin_button] با شورتکد';
$output = do_shortcode( $text );
echo $output;

پارامترها و نحوه پردازش

پارامتر content

متنی که باید پردازش شود. این متن می‌تواند شامل چند شورتکد، HTML و متن معمولی باشد:

$text = '<p>متن قبل [myplugin_button] و بعد از آن</p>';
echo do_shortcode( $text );

پارامتر ignore_html

اگر true باشد، شورتکدهای داخل تگ‌های HTML نادیده گرفته می‌شوند. این پارامتر برای جلوگیری از اجرای ناخواسته شورتکد در attributeهای HTML مفید است:

// شورتکد داخل alt اجرا نمی‌شود
do_shortcode( '<img alt="[myplugin_attr]" />', true );

نحوه پردازش درونی

تابع do_shortcode از یک regex پیچیده برای یافتن شورتکدها استفاده می‌کند. این regex در تابع get_shortcode_regex ساخته می‌شود و شامل تشخیص براکت‌های باز و بسته، attributeها و محتوای درونی است.

ترتیب پردازش:

  1. جستجوی تمام شورتکدهای ثبت‌شده در متن
  2. پردازش شورتکدهای درونی (nested) از داخل به بیرون
  3. جایگزینی هر شورتکد با خروجی callback
  4. بازگشت متن نهایی

پردازش شورتکدهای تو در تو

یکی از ظرافت‌های مهم do_shortcode، پردازش شورتکدهای تو در تو است. برخلاف تصور عمومی، این تابع به‌طور خودکار شورتکدهای درونی را پردازش نمی‌کند. اگر شورتکد بیرونی محتوای درونی دارد، باید خودتان در callback آن do_shortcode را فراخوانی کنید:

function myplugin_container_handler( $atts, $content = null ) {
    // پردازش شورتکدهای درونی
    $content = do_shortcode( $content );

    return '<div class="container">' . wp_kses_post( $content ) . '</div>';
}

بدون این فراخوانی، شورتکدهای درونی به‌صورت متن خام نمایش داده می‌شوند. برای مطالعه بیشتر، مطلب تابع add_shortcode را ببینید.

پردازش nested در سطح بیرونی

در برخی سناریوها، ممکن است بخواهید خودتان پردازش nested را کنترل کنید. تابع do_shortcode به‌طور پیش‌فرض این کار را از داخل به بیرون انجام می‌دهد. اما اگر می‌خواهید ترتیب را تغییر دهید، باید شورتکدها را دستی استخراج کنید.

نمونه‌های عملی در پروژه واقعی

اجرای شورتکد در فیلد سفارشی

$custom_content = get_post_meta( get_the_ID(), 'my_custom_content', true );
if ( ! empty( $custom_content ) ) {
    echo do_shortcode( $custom_content );
}

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

اجرای شورتکد در متن ویجت

add_filter( 'widget_text', 'do_shortcode' );
add_filter( 'widget_text', 'wpautop' );  // اختیاری، برای پاراگراف‌بندی

این الگو کلاسیک و پرکاربرد در پروژه‌های حرفه‌ای است. مطلب تابع register_widget راهنماست.

اجرای شورتکد در قالب PHP

<?php echo do_shortcode( '[myplugin_cta url="https://example.com"]کلیک کنید[/myplugin_cta]' ); ?>

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

اجرای شورتکد در توضیحات Term

$term = get_term( $term_id, 'category' );
if ( ! is_wp_error( $term ) && ! empty( $term->description ) ) {
    echo do_shortcode( $term->description );
}

برای مطالعه کامل taxonomy، مطلب تابع get_terms راهنماست.

اجرای شورتکد در ایمیل سفارش ووکامرس

add_action( 'woocommerce_email_before_order_table', function ( $order ) {
    $note = get_option( 'myplugin_email_note' );
    echo do_shortcode( $note );
}, 10, 1 );

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

اجرای شورتکد در محتوای برگه ورود

add_action( 'login_footer', function () {
    $content = get_option( 'myplugin_login_footer' );
    echo do_shortcode( $content );
} );

ترکیب با wp_kses_post برای امنیت

$content = get_post_meta( $post_id, 'my_field', true );
$rendered = do_shortcode( wp_kses_post( $content ) );
echo $rendered;

نکته مهم: ترتیب درست این است که ابتدا wp_kses_post را روی محتوای خام اجرا کنید و سپس do_shortcode را فراخوانی کنید. اما در برخی سناریوها، ممکن است ترتیب معکوس لازم باشد. برای مطالعه بیشتر، مطلب راهنمای Sanitization را ببینید.

اشتباهات رایج در استفاده از do_shortcode

اجرا در فیلد نامناسب

شایع‌ترین اشتباه. اگر do_shortcode را روی یک فیلد متنی ساده اجرا کنید که هیچ شورتکدی ندارد، هزینه پردازش regex پرداخت می‌شود بدون نتیجه. همیشه قبل از فراخوانی، بررسی کنید که فیلد ممکن است شورتکد داشته باشد.

نبود escape در خروجی

اگر شورتکد شما پارامتر از کاربر می‌گیرد و خروجی آن escape نشده باشد، به XSS منجر می‌شود. همیشه در callback شورتکد از esc_html، esc_attr و esc_url استفاده کنید. مطلب Output Escaping در وردپرس راهنمای کامل است.

فراخوانی do_shortcode در زمان اشتباه

اگر do_shortcode را در hook plugins_loaded فراخوانی کنید، ممکن است شورتکدهای ثبت‌نشده باشند چون add_shortcode در hook init اجرا می‌شود. همیشه در hook بعد از init فراخوانی کنید.

نبود بررسی شرط در قالب

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

if ( ! empty( $content ) ) {
    echo do_shortcode( $content );
}

نبود پردازش nested در callback

اگر شورتکد شما محتوای درونی دارد و do_shortcode را روی content فراخوانی نمی‌کنید، شورتکدهای درونی به‌صورت متن خام نمایش داده می‌شوند.

اجرای شورتکد روی HTML کامل صفحه

اگر do_shortcode را روی کل HTML صفحه اجرا کنید، ممکن است شورتکدهای ناخواسته در attributeهای HTML اجرا شوند. برای جلوگیری، از ignore_html = true استفاده کنید یا فقط روی محتوای موردنظر فراخوانی کنید.

نبود تست روی سناریوهای مرزی

تست‌هایی مثل «محتوای بدون شورتکد»، «شورتکد نامعتبر»، «شورتکد تودرتو»، «شورتکد با محتوای خالی» و «شورتکد در attribute HTML» را حتماً بنویسید.

امنیت و عملکرد در do_shortcode

این تابع یک عملیات پردازش regex است و به‌تنهایی امنیت را تهدید نمی‌کند. اما خروجی آن باید با احتیاط مدیریت شود:

  • محتوای ورودی از منبع نامطمئن باید ابتدا با wp_kses_post پاک شود
  • خروجی شورتکد باید با esc_html یا مشابه escape شود
  • در اجرای شورتکد در بخش‌های حساس مثل ایمیل یا پنل، محتوای ورودی را از منبع معتبر بگیرید
  • در فیلدهای سفارشی که ممکن است حاوی داده کاربر باشند، do_shortcode را با احتیاط فراخوانی کنید

برای مطالعه جامع مباحث امنیتی، مطلب SQL Injection Prevention در وردپرس مرجع است.

از نظر عملکرد، هر فراخوانی do_shortcode یک عملیات regex روی متن انجام می‌دهد. اگر در حلقه‌های بزرگ فراخوانی شود، هزینه قابل توجهی دارد:

  1. طول متن بر زمان پردازش اثر مستقیم دارد
  2. تعداد شورتکدهای ثبت‌شده بر پیچیدگی regex اثر می‌گذارد
  3. در سایت‌هایی با محتوای حجیم، بهتر است از cache استفاده کنید

برای مطالعه الگوهای بهینه، مطلب تابع get_transient و تابع set_transient راهنماست.

پرسش‌های پرتکرار درباره do_shortcode

تفاوت do_shortcode با add_shortcode چیست؟

add_shortcode() یک شورتکد جدید ثبت می‌کند، در حالی که do_shortcode() یک متن حاوی شورتکد را پردازش و اجرا می‌کند.

چرا شورتکد من در فیلد سفارشی اجرا نمی‌شود؟

وردپرس به‌طور پیش‌فرض فیلدهای سفارشی را پردازش نمی‌کند. باید در زمان نمایش مقدار فیلد، خودتان do_shortcode را فراخوانی کنید.

آیا می‌توان do_shortcode را در قالب فراخوانی کرد؟

بله، اما توصیه می‌شود در قالب به‌جای شورتکد از توابع PHP مستقیم استفاده کنید. اگر مجبور به استفاده از شورتکد هستید، از echo do_shortcode( ... ) استفاده کنید.

آیا شورتکدهای تو در تو کار می‌کنند؟

فقط در صورتی که در callback شورتکد بیرونی، do_shortcode را روی content فراخوانی کنید.

آیا می‌توان do_shortcode را در content ایمیل فراخوانی کرد؟

بله، اما توصیه می‌شود محتوای ورودی از منبع معتبر (پنل تنظیمات) باشد نه از کاربر.

آیا do_shortcode در بلاک گوتنبرگ کار می‌کند؟

بله، در بلاک Shortcode به‌طور خودکار پردازش می‌شود. اما در بلاک‌های دیگر که خروجی را مستقیماً HTML می‌سازند، نیاز به فراخوانی دستی است.

آیا do_shortcode امن است؟

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

نگاه فنی عمیق به do_shortcode

در سطح معماری، do_shortcode() یک عملیات regex پیچیده است که در فایل wp-includes/shortcodes.php پیاده‌سازی شده. این تابع از تابع get_shortcode_regex برای ساخت یک الگوی regex استفاده می‌کند که شامل تمام شورتکدهای ثبت‌شده است.

نکته ظریف اول، مسئله ترتیب پردازش nested است. این تابع به‌طور پیش‌فرض از یک الگوریتم از داخل به بیرون استفاده می‌کند که برای شورتکدهای درونی بازگشتی است. اما اگر شورتکدها به‌صورت غیرمتعارف نوشته شده باشند (مثلاً با کاراکترهای escape)، این الگوریتم می‌تواند رفتار غیرمنتظره داشته باشد.

نکته دوم، مسئله محتوای HTML در regex است. اگر HTML نامعتبر باشد یا شامل کاراکترهایی باشد که regex را می‌شکنند، ممکن است do_shortcode به‌درستی کار نکند. راهکار استاندارد، استفاده از پارامتر ignore_html یا پاکسازی HTML قبل از فراخوانی است.

مسئله سوم، تعامل با Shortcode Block در گوتنبرگ است. بلاک Shortcode خودش do_shortcode را فراخوانی می‌کند. اگر شما در callback یک بلاک سفارشی، do_shortcode را روی محتوای بلاک فراخوانی کنید، ممکن است شورتکد دو بار اجرا شود. این موضوع به‌ویژه در پروژه‌های ترکیبی (کلاسیک + بلاک) بسیار مهم است.

در نهایت، در پروژه‌های Enterprise توصیه می‌شود یک لایه Wrapper بسازید که do_shortcode را با cache ترکیب کند. به‌جای فراخوانی مستقیم در هر رندر، نتیجه را در Transient ذخیره کنید و در صورت تغییر محتوا، cache را پاک کنید. این الگو در سایت‌های پربازدید تفاوت چشمگیری ایجاد می‌کند. برای مطالعه بیشتر، مباحث WordPress Components و استانداردهای PSR مفید هستند. برای مطالعه بیشتر درباره خود وردپرس، WordPress در ویکی‌پدیا نقطه شروع خوبی است.

اگر در پروژه‌ای با مشکل اجرای دو بار شورتکد یا رفتار غیرمنتظره در nested مواجه شده‌اید، برای ما جالب است بدانید کدام راهکار عملاً به حل مسئله کمک کرده است. تجربه خود را در دیدگاه‌ها بنویسید تا برای سایر توسعه‌دهندگان هم مفید باشد.