FA-TOOLS — Header Component

چگونه پست تایپ سفارشی بدون افزونه در وردپرس بسازیم؟

خلاصه سریع مقاله:

ساخت پست تایپ سفارشی (CPT) با کدنویسی مستقیم در فایل functions.php یا یک پلاگین اختصاصی، سرعت سایت شما را افزایش داده و وابستگی به افزونه‌های سنگین را صفر می‌کند. در این راهنما، کد کامل استاندارد، نحوه اضافه کردن تاکسونومی، مدیریت خطای 404، فعال‌سازی ویرایشگر گوتنبرگ و نحوه فراخوانی داده‌ها در قالب را به‌صورت حرفه‌ای بررسی می‌کنیم.

ساخت پست تایپ سفارشی بدون استفاده از افزونه، موثرترین روش برای توسعه ساختاریافته، سریع و ایمن وب‌سایت‌های وردپرسی است. با ثبت اختصاصی Custom Post Type از طریق تابع register_post_type، شما مدیریت کامل بر پایگاه داده، کوئری‌ها و نحوه نمایش محتوا خواهید داشت و پایگاه داده خود را از جداول اضافی افزونه‌ها پاک نگه می‌دارید.

پست تایپ سفارشی (Custom Post Type) چیست؟

چگونه پست تایپ سفارشی بدون افزونه بسازیم — تصویر 1

پست تایپ سفارشی (CPT) یکی از قابلیت‌های هسته وردپرس است که به شما امکان می‌دهد نوع جدیدی از محتوا (غیر از «نوشته‌ها» و «برگه‌ها») با ساختار، آرشیو و ویژگی‌های کاملاً مستقل ایجاد کنید.

وردپرس به‌طور پیش‌فرض دارای پست تایپ‌هایی مانند Post (نوشته)، Page (برگه)، Attachment (رسانه) و Revision (پیش‌نویس) است. اما وقتی می‌خواهید بخش‌هایی مانند «نمونه‌کارها»، «دوره‌های آموزشی»، «املاک»، «پزشکان» یا «نظرات مشتریان» را مدیریت کنید، استفاده از نوشته‌های معمولی ساختار سایت را به هم می‌ریزد. در این شرایط، ایجاد یک CPT اختصاصی بهترین راهکار معماری محتوا است.

چرا نباید از افزونه برای ساخت CPT استفاده کنیم؟

استفاده از افزونه‌هایی نظیر Custom Post Type UI اگرچه آسان است، اما لایه‌های پردازشی اضافی به وردپرس تحمیل می‌کند. علاوه بر این، با غیرفعال شدن افزونه، دسترسی به مدیریت محتوای ساخته‌شده در پیشخوان از دست می‌رود (هرچند داده‌ها در دیتابیس باقی می‌مانند).

معیار مقایسه روش کدنویسی مستقیم (بدون افزونه) استفاده از افزونه (مانند CPT UI)
کارایی و سرعت (Performance) بسیار بالا (بدون بارگذاری کدهای اضافی) کاهش جزیی سرعت به دلیل چک کردن گزینه‌ها در دیتابیس
وابستگی (Dependency) صفر؛ وابسته به پوسته یا پلاگین اختصاصی شما وابستگی کامل به فعال بودن و بروزرسانی افزونه
انتقال‌پذیری (Portability) بسیار آسان با کپی کردن یک قطعه کد نیازمند خروجی و ورودی گرفتن از تنظیمات افزونه
کنترل بر REST API و گوتنبرگ دقیق، مستقیم و قابل سفارشی‌سازی کامل محدود به تنظیمات گرافیکی افزونه

کد جامع و گام‌به‌گام ثبت پست تایپ سفارشی

برای ایجاد یک CPT حرفه‌ای، کد زیر را در فایل functions.php پوسته فعال یا بهتر از آن، در یک افزونه اختصاصی (Must-Use Plugin) قرار دهید. در این مثال، یک پست تایپ به نام «نمونه‌کارها» (portfolio) می‌سازیم.

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

function custom_register_portfolio_cpt() {

    $labels = array(
        'name'                  => _x( 'نمونه‌کارها', 'Post Type General Name', 'text_domain' ),
        'singular_name'         => _x( 'نمونه‌کار', 'Post Type Singular Name', 'text_domain' ),
        'menu_name'             => __( 'نمونه‌کارها', 'text_domain' ),
        'name_admin_bar'        => __( 'نمونه‌کار', 'text_domain' ),
        'archives'              => __( 'آرشیو نمونه‌کارها', 'text_domain' ),
        'attributes'            => __( 'ویژگی‌های نمونه‌کار', 'text_domain' ),
        'parent_item_colon'     => __( 'نمونه‌کار والد:', 'text_domain' ),
        'all_items'             => __( 'همه نمونه‌کارها', 'text_domain' ),
        'add_new_item'          => __( 'افزودن نمونه‌کار جدید', 'text_domain' ),
        'add_new'               => __( 'افزودن جدید', 'text_domain' ),
        'new_item'              => __( 'نمونه‌کار جدید', 'text_domain' ),
        'edit_item'             => __( 'ویرایش نمونه‌کار', 'text_domain' ),
        'update_item'           => __( 'بروزرسانی نمونه‌کار', 'text_domain' ),
        'view_item'             => __( 'مشاهده نمونه‌کار', 'text_domain' ),
        'view_items'            => __( 'مشاهده نمونه‌کارها', 'text_domain' ),
        'search_items'          => __( 'جستجوی نمونه‌کار', 'text_domain' ),
        'not_found'             => __( 'یافت نشد', 'text_domain' ),
        'not_found_in_trash'    => __( 'در زباله‌دان یافت نشد', 'text_domain' ),
        'featured_image'        => __( 'تصویر شاخص', 'text_domain' ),
        'set_featured_image'    => __( 'تنظیم تصویر شاخص', 'text_domain' ),
        'remove_featured_image' => __( 'حذف تصویر شاخص', 'text_domain' ),
        'use_featured_image'    => __( 'استفاده به عنوان تصویر شاخص', 'text_domain' ),
        'insert_into_item'      => __( 'افزودن به نمونه‌کار', 'text_domain' ),
        'uploaded_to_this_item' => __( 'بارگذاری شده در این نمونه‌کار', 'text_domain' ),
        'items_list'            => __( 'لیست نمونه‌کارها', 'text_domain' ),
        'items_list_navigation' => __( 'ناوبری لیست نمونه‌کارها', 'text_domain' ),
        'filter_items_list'     => __( 'فیلتر لیست نمونه‌کارها', 'text_domain' ),
    );

    $args = array(
        'label'                 => __( 'نمونه‌کار', 'text_domain' ),
        'description'           => __( 'پست تایپ اختصاصی برای نمایش نمونه‌کارها', 'text_domain' ),
        'labels'                => $labels,
        'supports'              => array( 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields', 'revisions' ),
        'taxonomies'            => array(),
        'hierarchical'          => false,
        'public'                => true,
        'show_ui'               => true,
        'show_in_menu'          => true,
        'menu_position'         => 5,
        'menu_icon'             => 'dashicons-portfolio',
        'show_in_admin_bar'     => true,
        'show_in_nav_menus'     => true,
        'can_export'            => true,
        'has_archive'           => true,
        'exclude_from_search'   => false,
        'publicly_queryable'    => true,
        'capability_type'       => 'post',
        'show_in_rest'          => true, // فعال‌سازی ویرایشگر گوتنبرگ و REST API
        'rewrite'               => array( 'slug' => 'portfolio', 'with_front' => false ),
    );

    register_post_type( 'portfolio', $args );

}
add_action( 'init', 'custom_register_portfolio_cpt', 0 );

تحلیل پارامترهای کلیدی کد بالا:

  • show_in_rest: تنظیم این آرگومان روی true حیاتی است. اگر این مقدار اضافه نشود، ویرایشگر جدید وردپرس (گوتنبرگ) برای این پست تایپ فعال نشده و ویرایشگر کلاسیک قدیمی بارگذاری می‌شود.
  • has_archive: فعال بودن آن (true) باعث می‌شود یک صفحه آرشیو خودکار در آدرس yoursite.com/portfolio ایجاد شود.
  • supports: مشخص می‌کند چه قابلیت‌هایی (عنوان، ویرایشگر متن، تصویر شاخص، چکیده و زمینه سفارشی) در صفحه ویرایش فعال باشند.
  • menu_icon: آیکون بخش مدیریت را تعیین می‌کند. می‌توانید از نام کلاس‌های Dashicons وردپرس استفاده کنید.

افزودن دسته‌بندی سفارشی (Custom Taxonomy)

پست تایپ‌های سفارشی به‌طور پیش‌فرض به دسته‌بندی‌ها و برچسب‌های عمومی وردپرس متصل نیستند (و بهتر است نباشند). برای دسته‌بندی مجزای محتوای خود، باید یک Taxonomy سفارشی بسازید.

function custom_register_portfolio_taxonomy() {

    $labels = array(
        'name'              => _x( 'دسته‌بندی‌های نمونه‌کار', 'taxonomy general name', 'text_domain' ),
        'singular_name'     => _x( 'دسته‌بندی نمونه‌کار', 'taxonomy singular name', 'text_domain' ),
        'search_items'      => __( 'جستجوی دسته‌ها', 'text_domain' ),
        'all_items'         => __( 'همه دسته‌ها', 'text_domain' ),
        'parent_item'       => __( 'دسته والد', 'text_domain' ),
        'parent_item_colon' => __( 'دسته والد:', 'text_domain' ),
        'edit_item'         => __( 'ویرایش دسته', 'text_domain' ),
        'update_item'       => __( 'بروزرسانی دسته', 'text_domain' ),
        'add_new_item'      => __( 'افزودن دسته جدید', 'text_domain' ),
        'new_item_name'     => __( 'نام دسته جدید', 'text_domain' ),
        'menu_name'         => __( 'دسته‌بندی‌ها', 'text_domain' ),
    );

    $args = array(
        'hierarchical'      => true, // ساختار مادر/فرزندی مثل دسته‌های نوشته
        'labels'            => $labels,
        'show_ui'           => true,
        'show_admin_column' => true,
        'query_var'         => true,
        'show_in_rest'      => true, // نمایش در ویرایشگر گوتنبرگ
        'rewrite'           => array( 'slug' => 'portfolio-category' ),
    );

    register_taxonomy( 'portfolio_cat', array( 'portfolio' ), $args );

}
add_action( 'init', 'custom_register_portfolio_taxonomy', 0 );

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

برای نمایش محتوای پست تایپ ساخته شده در پوسته، وردپرس از سیستم ساختار فایل‌ها (Template Hierarchy) استفاده می‌کند. شما می‌توانید فایل‌های زیر را در پوشه قالب خود بسازید:

  • single-portfolio.php: برای نمایش تکی هر نمونه‌کار.
  • archive-portfolio.php: برای نمایش صفحه لیست/آرشیو نمونه‌کارها.
  • taxonomy-portfolio_cat.php: برای نمایش صفحه دسته‌بندی‌های اختصاصی نمونه‌کار.

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

<?php
$args = array(
    'post_type'      => 'portfolio',
    'posts_per_page' => 6,
    'post_status'    => 'publish',
    'orderby'        => 'date',
    'order'          => 'DESC',
);

$portfolio_query = new WP_Query( $args );

if ( $portfolio_query->have_posts() ) :
    echo '<div class="portfolio-grid">';
    while ( $portfolio_query->have_posts() ) : $portfolio_query->the_post(); ?>
        
        <article id="post-<?php the_ID(); ?>" <?php post_class('portfolio-item'); ?>>
            <a href="<?php the_permalink(); ?>">
                <?php if ( has_post_thumbnail() ) : ?>
                    <?php the_post_thumbnail('medium'); ?>
                <?php endif; ?>
                <h3><?php the_title(); ?></h3>
            </a>
            <div class="excerpt"><?php the_excerpt(); ?></div>
        </article>

    <?php endwhile;
    echo '</div>';
    wp_reset_postdata(); // بازنشانی کوئری وردپرس
else :
    echo '<p>هیچ نمونه‌کاری یافت نشد.</p>';
endif;
?>

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

نکات تخصصی و اشتباهات مهلک توسعه‌دهندگان

۱. عدم درج تابع flush_rewrite_rules در هوک عمومی

بزرگ‌ترین اشتباه این است که تابع flush_rewrite_rules() را مستقیماً داخل هوک init اجرا کنید. این کار باعث می‌شود پیوندهای یکتا در هر بار بارگذاری صفحه بازنویسی شوند که افت شدید سرعت سایت و درگیر شدن دیتابیس را به همراه دارد. راه درست: پس از ثبت کد، فقط یک‌بار به مسیر تنظیمات > پیوندهای یکتا رفته و روی «ذخیره تغییرات» کلیک کنید.

۲. تداخل پیوندهای یکتا (Slug Conflict)

نام نامک (slug) پست تایپ نباید با نام یک برگه (Page) یا نام یک دسته‌بندی یکسان باشد. اگر برگه ای با آدرس site.com/portfolio دارید و slug پست تایپ را هم portfolio بگذارید، وردپرس دچار تداخل شده و خطای 404 یا نمایش اشتباه برگه رخ می‌دهد.

۳. اضافه کردن CPT به جستجوی اصلی سایت

به‌طور پیش‌فرض، نتایج جستجوی سایت ممکن است شامل پست تایپ جدید نشود. برای اضافه کردن آن به کوئری اصلی جستجو از هوک pre_get_posts استفاده کنید:

function add_cpt_to_search_query( $query ) {
    if ( $query->is_search() && $query->is_main_query() && ! is_admin() ) {
        $query->set( 'post_type', array( 'post', 'portfolio' ) );
    }
}
add_action( 'pre_get_posts', 'add_cpt_to_search_query' );

عیب‌یابی سریع مشکلات رایج

مشکل ۱: دریافت خطای 404 هنگام باز کردن تک‌صفحه‌های پست تایپ

علت: جدول بازنویسی آدرس‌های وردپرس (Rewrite Rules) بروزرسانی نشده است.
راه‌حل: وارد پیشخوان وردپرس شوید، به مسیر تنظیمات > پیوندهای یکتا بروید و بدون تغییر هیچ گزینه‌ای، فقط روی دکمه «ذخیره تغییرات» کلیک کنید.

مشکل ۲: عدم نمایش ویرایشگر بلوک (گوتنبرگ) و ظاهر شدن ویرایشگر قدیمی

علت: پارامتر REST API در کد ثبت پست تایپ غیرفعال است.
راه‌حل: مطمئن شوید عبارت 'show_in_rest' => true در آرایه $args آرگومان‌های پست تایپ و تاکسونومی قرار دارد.

مشکل ۳: پست تایپ سفارشی در آرشیو اصلی یا برگه خانه قرار نمی‌گیرد

علت: کوئری اصلی وردپرس فقط نوشته‌های عادی (post) را فراخوانی می‌کند.
راه‌حل: از هوک pre_get_posts استفاده کنید تا پست تایپ جدید به حلقه اصلی اضافه شود.

پرسش‌های متداول

آیا ساخت پست تایپ بدون افزونه باعث پاک شدن داده‌ها هنگام تغییر قالب می‌شود؟

اگر کد را در فایل functions.php قالب قرار دهید، با تغییر قالب پست تایپ در پیشخوان ناپدید می‌شود (اما داده‌ها در دیتابیس محفوظ می‌مانند). برای جلوگیری از این مشکل، کدهای CPT را در یک پلاگین اختصاصی (Must-Use Plugin) بنویسید.

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

هیچ محدودیت فنی در تعداد پست تایپ وجود ندارد. با این حال ساخت تعداد بسیار زیادی CPT به دلیل افزایش پیچیدگی کوئری‌ها ممکن است بر بهینه‌سازی دیتابیس تاثیر بگذارد.

فرق بین Hierarchical (سلسله‌مراتبی) و Non-hierarchical چیست؟

پست تایپ‌های سلسله‌مراتبی (مثل «برگه‌ها») می‌توانند والد و فرزند داشته باشند. پست تایپ‌های غیر سلسله‌مراتبی (مثل «نوشته‌ها») ساختار هم‌سطح دارند. این ویژگی با آرگومان 'hierarchical' => true/false تعیین می‌شود.

چگونه زمینه‌های دلخواه (Custom Fields) به پست تایپ اضافه کنیم؟

می‌توانید از متاباکس‌های اختصاصی وردپرس (با تابع add_meta_box) استفاده کنید یا از افزونه Advanced Custom Fields (ACF) صرفاً برای اضافه کردن فیلدها به CPT ساخته‌شده کمک بگیرید. همچنین قطعات برنامه‌نویسی متنوعی در آرشیو کدهای برنامه‌نویسی جهت مدیریت سفارشی زمینه‌ها در دسترس است.

Table of Contents

آخرین نوشته‌ها

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *