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

دریافت دسته‌بندی

برای دریافت اطلاعات دسته‌بندی، توابع مختلفی وجود دارد که بسته به سناریو به‌کار می‌روند:

get_category( $cat_id );                    // با شناسه
get_category_by_slug( 'news' );              // با اسلاگ
get_category_by_path( 'parent/child' );      // با مسیر
get_the_category( $post_id );                // دسته‌های نوشته
get_categories( $args );                     // لیست دسته‌ها
get_category_link( $cat_id );                // لینک دسته
get_cat_name( $cat_id );                     // نام
get_cat_ID( 'News' );                        // شناسه با نام
get_term( $cat_id, 'category' );             // از توابع تاکسونومی

نکته‌ها: یک — بازگشتی‌ها: get_category شیء WP_Term برمی‌گرداند؛ اگر نبود، null. دو — get_the_category: آرایه‌ای از دسته‌های نوشته در حلقه یا با شناسه. سه — معادل‌های تاکسونومی: از وردپرس ۴.۴ به بعد، توابع get_term، get_terms و مشابه، برای دسته‌بندی هم کار می‌کنند. تفاوت و کاربردشان در تاکسونومی سفارشی. الگوی بررسی:

$category = get_category( $cat_id );
if ( $category && ! is_wp_error( $category ) ) {
    echo esc_html( $category->name );
}

نمایش دسته در حلقه

نمایش دسته‌های یک نوشته، دو تابع متداول دارد:

the_category( ', ' );                       // چاپ دسته‌ها با جداکننده
get_the_category( $post_id );                // بازگرداندن آرایه
the_category( '، ', 'multiple', $post_id );  // حالات مختلف

پارامترهای the_category: یک — جداکننده: متن بین دسته‌ها. دو — حالت نمایش: single (فقط اولین دسته)، multiple (همه، پیش‌فرض)، multiple با تنظیم دیگر. سه — شناسه: اختیاری. الگوی سفارشی:

$categories = get_the_category();
if ( ! empty( $categories ) ) :
    echo '<div class="post-categories">';
    foreach ( $categories as $category ) :
        printf(
            '<a href="%s" class="cat-link">%s</a>',
            esc_url( get_category_link( $category->term_id ) ),
            esc_html( $category->name )
        );
    endforeach;
    echo '</div>';
endif;

چرا این الگو بهتر از the_category است؟ چون امکان کنترل کلاس‌ها، ترتیب، و escape اختصاصی می‌دهد. راهنمای تفکیک در توابع دادهٔ نوشته. یک نکتهٔ سئویی: در کارت‌های نوشته، بهتر است فقط دستهٔ اصلی نمایش داده شود، نه همهٔ دسته‌ها — برای جلوگیری از شلوغی و برای تأکید بر دستهٔ اصلی. راهنمای دستهٔ اصلی در سئوی درون‌صفحه.

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

لینک دسته‌بندی، کاربر را به آرشیو دسته می‌برد:

get_category_link( $cat_id );           // لینک دسته
get_term_link( $term );                 // لینک هر ترم
get_term_link( 'news', 'category' );    // لینک با اسلاگ

نکته: از وردپرس ۴.۴ به بعد، get_term_link برای دسته‌بندی هم کار می‌کند و استانداردتر است. همیشه خروجی را با esc_url escape کنید:

<a href="<?php echo esc_url( get_category_link( $cat->term_id ) ); ?>">
    <?php echo esc_html( $cat->name ); ?>
</a>

راهنمای ساختار URL در ساختار URL و سئو و توابع لینک و URL.

ساختار سلسله‌مراتبی

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

$cat->parent;                                    // شناسهٔ والد (0 برای ریشه)
get_category_parents( $cat_id, true, ' / ' );      // مسیر کامل از ریشه
get_ancestors( $cat_id, 'category' );             // آرایهٔ والدین
cat_is_ancestor_of( $cat_a, $cat_b );              // آیا A والد B است؟
get_term_children( $cat_id, 'category' );          // فرزندان

نمایش مسیر سلسله‌مراتبی در صفحهٔ تک‌نوشته:

$categories = get_the_category();
if ( ! empty( $categories ) ) {
    $cat = $categories[0];
    $parents = get_category_parents( $cat->term_id, false, ' / ' );
    if ( ! is_wp_error( $parents ) ) {
        echo '<div class="breadcrumbs">' . $parents . '</div>';
    }
}

نکته: get_category_parents خروجی HTML آماده می‌دهد. پارامتر دوم (true/false) تعیین می‌کند پیوندها به‌صورت لینک باشند یا متن ساده. الگوهای سلسله‌مراتبی در تاکسونومی سفارشی.

شمارش نوشته‌ها

شمارش نوشته‌های یک دسته، برای نمایش تعداد یا فیلترکردن دسته‌های خالی مفید است:

$cat->count;                                          // تعداد در شیء دسته
$cat->category_count;                                 // معادل قدیمی
get_term( $cat_id, 'category' )->count;              // با تابع تاکسونومی

در لیست دسته‌ها، با get_categories یا get_terms:

$categories = get_categories( array(
    'orderby'    => 'name',
    'order'      => 'ASC',
    'hide_empty' => true,
    'parent'     => 0,
) );

foreach ( $categories as $cat ) {
    printf(
        '<a href="%s">%s (%d)</a>',
        esc_url( get_category_link( $cat->term_id ) ),
        esc_html( $cat->name ),
        (int) $cat->count
    );
}

نکتهٔ عملکردی: فیلد count در دسته‌های پربازدید، کوئری شمارش سنگینی دارد؛ اگر فقط برای نمایش است، استفاده از count cache شده توصیه می‌شود. راهنمای بهینه‌سازی در بهینه‌سازی کوئری‌ها.

متادیتای دسته

از وردپرس ۴.۴ به بعد، دسته‌ها هم می‌توانند متادیتای سفارشی داشته باشند:

get_term_meta( $cat_id, '_cat_color', true );       // خواندن
update_term_meta( $cat_id, '_cat_color', $value );   // به‌روزرسانی
add_term_meta( $cat_id, '_cat_icon', $icon_id );     // افزودن
delete_term_meta( $cat_id, '_cat_color' );           // حذف
get_term_meta( $cat_id );                             // همهٔ متاها

نمایش متادیتا در front-end:

$color = get_term_meta( $cat->term_id, '_cat_color', true );
if ( $color ) {
    printf(
        '<span class="cat-badge" style="background:%s;">%s</span>',
        esc_attr( $color ),
        esc_html( $cat->name )
    );
}

نکته: همیشه رنگ یا دادهٔ متادیتا را قبل از چاپ در ویژگی‌های HTML، با esc_attr escape کنید. راهنمای کامل متادیتای ترم در تاکسونومی سفارشی و توابع متادیتا.

ساخت و ویرایش دسته

ساخت و ویرایش دسته، با توابع اختصاصی انجام می‌شود:

// ساخت
$result = wp_insert_term( 'اخبار فوری', 'category', array(
    'description' => 'دستهٔ اخبار فوری',
    'parent'      => $parent_id,
    'slug'        => 'breaking-news',
) );

if ( is_wp_error( $result ) ) {
    error_log( $result->get_error_message() );
} else {
    $new_cat_id = $result['term_id'];
}

// به‌روزرسانی
wp_update_term( $cat_id, 'category', array(
    'name'        => 'اخبار جدید',
    'description' => 'توضیحات جدید',
) );

// معادل‌های قدیمی
wp_create_category( 'نام', $parent_id );
wp_update_category( array( 'cat_ID' => $cat_id, 'cat_name' => 'نام جدید' ) );

نکته‌ها: یک — wp_insert_term: استاندارد جدید و سازگار با تاکسونومی‌های سفارشی. دو — خروجی: در موفقیت، آرایه‌ای با term_id و term_taxonomy_id؛ در خطا، WP_Error. سه — معادل‌های قدیمی: wp_create_category و wp_update_category همچنان کار می‌کنند ولی برای تاکسونومی سفارشی کار نمی‌کنند. تفصیل در ساخت تاکسونومی سفارشی.

حذف دسته

حذف دسته، با یک تابع و دو نکتهٔ حساس انجام می‌شود:

wp_delete_term( $cat_id, 'category' );
wp_delete_category( $cat_id ); // معادل قدیمی

نکته‌ها: یک — قبل از حذف، جایگزینی تعیین کنید: وردپرس به‌طور پیش‌فرض، نوشته‌های دستهٔ حذف‌شده را به دستهٔ پیش‌فرض (Uncategorized) منتقل می‌کند. برای تعیین دستهٔ جایگزین، از wp_delete_term با پارامتر $args استفاده کنید:

wp_delete_term( $cat_id, 'category', array(
    'default' => $new_cat_id,
) );

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

کوئری بر اساس دسته

پرس‌وجوی نوشته‌ها بر اساس دسته، در دو سطح انجام می‌شود: در حلقهٔ اصلی و در کوئری سفارشی:

// در حلقهٔ اصلی
if ( is_category( 'news' ) ) {
    // آرشیو دستهٔ خبر
}

// با WP_Query
$args = array(
    'post_type'      => 'post',
    'posts_per_page' => 10,
    'cat'            => 5,                        // فقط شناسه
    // یا
    'category_name'  => 'news',                   // فقط اسلاگ
    // یا
    'category__in'   => array( 5, 7, 12 ),        // یکی از چند دسته
    'category__and'  => array( 5, 7 ),            // همهٔ این دسته‌ها
    'category__not_in' => array( 3, 8 ),          // نه این دسته‌ها
);
$query = new WP_Query( $args );

پارامترهای category__in و category__and کاربرد متفاوتی دارند: یک — in: نوشته‌هایی که در یکی از دسته‌های لیست هستند. دو — and: نوشته‌هایی که در همهٔ دسته‌های لیست هستند. تفصیل کامل در کدنویسی کوئری سفارشی و توابع کوئری سفارشی.

انتخاب بین in و and در کوئری دسته، تفاوت بین نمایش «تمام نوشته‌های مرتبط» و «نوشته‌های دقیقاً منطبق» است. تصمیم درست، به هدف صفحه بستگی دارد.

الگوهای ترکیبی

سه الگوی پرکاربرد در قالب‌های حرفه‌ای: یک — نوار دسته در آرشیو:

$categories = get_categories( array(
    'hide_empty' => true,
    'parent'     => 0,
    'orderby'    => 'count',
    'order'      => 'DESC',
) );

echo '<nav class="category-nav">';
foreach ( $categories as $cat ) {
    printf(
        '<a href="%s">%s <span>(%d)</span></a>',
        esc_url( get_category_link( $cat->term_id ) ),
        esc_html( $cat->name ),
        (int) $cat->count
    );
}
echo '</nav>';

دو — مسیر سلسله‌مراتبی در آرشیو:

$current_cat = get_queried_object();
if ( $current_cat && isset( $current_cat->term_id ) ) {
    $parents = get_category_parents( $current_cat->term_id, true, ' / ' );
    if ( ! is_wp_error( $parents ) ) {
        printf( '<div class="breadcrumb">%s</div>', $parents );
    }
}

سه — نمایش درست دسته با متادیتا:

$categories = get_the_category();
if ( ! empty( $categories ) ) :
    echo '<div class="post-categories">';
    foreach ( $categories as $category ) :
        $color = get_term_meta( $category->term_id, '_cat_color', true );
        printf(
            '<a href="%s" class="cat-link"%s>%s</a>',
            esc_url( get_category_link( $category->term_id ) ),
            $color ? ' style="background:' . esc_attr( $color ) . '"' : '',
            esc_html( $category->name )
        );
    endforeach;
    echo '</div>';
endif;

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

escape خروجی و امنیت

سه قاعدهٔ الزامی در کار با دسته‌ها: یک — escape در نمایش:

echo esc_html( $cat->name );
echo esc_url( get_category_link( $cat->term_id ) );
echo wp_kses_post( $cat->description ); // اگر HTML مجاز است

دو — بررسی is_wp_error: در خروجی توابعی مثل get_term_link و get_category_parents:

$link = get_term_link( $cat->term_id );
if ( ! is_wp_error( $link ) ) {
    echo esc_url( $link );
}

سه — بررسی current_user_can در ساخت و ویرایش: پیش از wp_insert_term یا wp_update_term، دسترسی کاربر را چک کنید:

if ( ! current_user_can( 'manage_categories' ) ) {
    return;
}

راهنمای کامل در PHP امن در وردپرس، پاک‌سازی داده‌ها، اعتبارسنجی داده‌ها، و توابع نقش و دسترسی. یک آسیب‌پذیری شایع که در پرونده‌های امنیتی دیده‌ام: فرم ویرایش دسته در پیشخوان که current_user_can را نداشت؛ نتیجه این بود که هر کاربر با نقش نویسنده هم می‌توانست ساختار دسته‌ها را تغییر دهد.

اشتباهات رایج

توابع دسته‌بندی وردپرس، در ده گروه مرور شدند: دریافت، نمایش، لینک، سلسله‌مراتبی، شمارش، متادیتا، ساخت و ویرایش، حذف، کوئری، و escape خروجی. تسلط بر این فهرست، در هر پروژهٔ محتوایی — از وبلاگ شخصی تا سایت خبری و آموزشی — سرعت کار را چند برابر می‌کند. اگر امروز یک کار در این مسیر انجام می‌دهید: یکی از فایل‌های قالب فعلی خود را باز کنید و ببینید کدام بخش‌ها با the_category پیش‌فرض نوشته شده و کدام بخش می‌تواند با الگوی escape‌شدهٔ سفارشی بازنویسی شود؛ همان بخش‌ها، فهرست اقدام شماست. اگر تجربه‌ای از یک باگ در نمایش یا حذف دسته دارید، در دیدگاه‌ها بنویسید؛ همان گزارش‌های واقعی، این راهنما را برای توسعه‌دهندهٔ بعدی دقیق‌تر می‌کند. 🏷️