افزودن گزینه‌های اضافی (Addons) به محصولات ووکامرس

افزودن به علاقه مندی

شاید براتون پیش اومده باشه که بخواید برای یک محصول در ووکامرس چند گزینه اضافی (مثل نصب و راه‌اندازی، پشتیبانی، آموزش و…) تعریف کنید و قیمت این گزینه‌ها رو به صورت داینامیک به قیمت محصول اضافه کنید.

در این آموزش، یه کد حرفه‌ای براتون آماده کردم که:

✅ گزینه‌های اضافی رو به صورت داینامیک برای هر محصول ایجاد می‌کنید.
✅ امکان تعیین تخفیف درصدی برای هر گزینه وجود داره.
✅ موقع تیک زدن گزینه‌ها، قیمت محصول به صورت زنده (Ajax) تغییر می‌کنه.
✅ قیمت نهایی محصول به همراه گزینه‌ها در سبد خرید و پرداخت درست جمع‌بندی می‌شه.

کاربرد این قابلیت

  • فروش خدمات جانبی مثل نصب و آموزش
  • ارائه پشتیبانی‌های خاص
  • فروش ماژول‌ها یا لایسنس‌های اضافی به همراه محصول

آموزش قدم‌به‌قدم

  1. قرار دادن کد

کد زیر رو توی فایل functions.php قالب فرزندتون یا افزونه اختصاصی بذارید:

PHP
// ✅ متاباکس مدیریت محصول
add_action('woocommerce_product_options_general_product_data', 'custom_product_addons_fields');
function custom_product_addons_fields() {
    global $post;
    echo '<div class="options_group">';
    echo '<p><strong>گزینه‌های اضافی محصول (تخفیف‌دار)</strong></p>';

    $addons = get_post_meta($post->ID, '_custom_product_addons', true);
    if (!is_array($addons)) {
        $addons = array(array('title' => '', 'price' => '', 'discount' => ''));
    }

    echo '<div id="custom-addons-wrapper">';
    foreach ($addons as $index => $addon) {
        ?>
        <div class="custom-addon" style="margin-bottom:15px; padding:10px; border:1px solid #ddd;">
            <p>
                <label>عنوان گزینه:</label>
                <input type="text" name="custom_addons[<?php echo $index; ?>][title]" value="<?php echo esc_attr($addon['title']); ?>" style="width:25%;" placeholder="مثال: نصب و راه‌اندازی" />
                 
                <label>قیمت:</label>
                <input type="number" name="custom_addons[<?php echo $index; ?>][price]" value="<?php echo esc_attr($addon['price']); ?>" style="width:15%;" placeholder="مثال: 100000" />
                 
                <label>درصد تخفیف (اختیاری):</label>
                <input type="number" name="custom_addons[<?php echo $index; ?>][discount]" value="<?php echo isset($addon['discount']) ? esc_attr($addon['discount']) : ''; ?>" style="width:15%;" placeholder="مثال: 10 (برای 10٪)" />
                <button type="button" class="remove-addon button">حذف</button>
            </p>
            <small style="color: #555;">🔹 درصد تخفیف اختیاری است؛ اگر خالی بگذارید تخفیف اعمال نمی‌شود.</small>
        </div>
        <?php
    }
    echo '</div>';
    echo '<p><button type="button" class="add-addon button">+ گزینه جدید</button></p>';
    ?>
    <script>
    jQuery(function($){
        var wrapper = $('#custom-addons-wrapper');
        var index = <?php echo count($addons); ?>;
        $('.add-addon').on('click', function(e){
            e.preventDefault();
            var html = '<div class="custom-addon" style="margin-bottom:15px; padding:10px; border:1px solid #ddd;">' +
                '<p>' +
                '<label>عنوان گزینه:</label> ' +
                '<input type="text" name="custom_addons['+index+'][title]" style="width:25%;" placeholder="مثال: نصب و راه‌اندازی" /> ' +
                '  <label>قیمت:</label> ' +
                '<input type="number" name="custom_addons['+index+'][price]" style="width:15%;" placeholder="مثال: 100000" /> ' +
                '  <label>درصد تخفیف (اختیاری):</label> ' +
                '<input type="number" name="custom_addons['+index+'][discount]" style="width:15%;" placeholder="مثال: 10 (برای 10٪)" /> ' +
                '<button type="button" class="remove-addon button">حذف</button>' +
                '</p>' +
                '<small style="color: #555;">🔹 درصد تخفیف اختیاری است؛ اگر خالی بگذارید تخفیف اعمال نمی‌شود.</small>' +
                '</div>';
            wrapper.append(html);
            index++;
        });
        wrapper.on('click', '.remove-addon', function(e){
            e.preventDefault();
            $(this).closest('.custom-addon').remove();
        });
    });
    </script>
    <?php
    echo '</div>';
}

// ✅ ذخیره متا
add_action('woocommerce_process_product_meta', 'custom_product_addons_fields_save');
function custom_product_addons_fields_save($post_id) {
    if (isset($_POST['custom_addons'])) {
        $addons = array();
        foreach ($_POST['custom_addons'] as $addon) {
            if (!empty($addon['title']) && isset($addon['price'])) {
                $addons[] = array(
                    'title' => sanitize_text_field($addon['title']),
                    'price' => floatval($addon['price']),
                    'discount' => isset($addon['discount']) ? intval($addon['discount']) : 0
                );
            }
        }
        update_post_meta($post_id, '_custom_product_addons', $addons);
    } else {
        delete_post_meta($post_id, '_custom_product_addons');
    }
}

// ✅ نمایش گزینه‌ها + آپدیت زنده قیمت
add_action('woocommerce_before_add_to_cart_button', 'custom_product_addons_display');
function custom_product_addons_display() {
    global $product;
    $addons = get_post_meta($product->get_id(), '_custom_product_addons', true);
    if (!is_array($addons) || empty($addons)) return;

    echo '<div class="custom-product-addons" style="margin-top:15px;">';
    foreach ($addons as $index => $addon) {
        $original_price = $addon['price'];
        $discount = isset($addon['discount']) ? $addon['discount'] : 0;
        $final_price = $original_price;

        if ($discount > 0 && $discount < 100) {
            $final_price = $original_price - ($original_price * $discount / 100);
        }

        echo '<div class="custom-addon-option" style="margin-bottom:10px; display:flex; align-items:center; gap:10px;">';
        echo '<label style="cursor:pointer; display:flex; align-items:center; gap:10px;">';
        echo '<input type="checkbox" name="addon_option['.$index.']" value="'.esc_attr($final_price).'" data-price="'.esc_attr($final_price).'" class="addon-checkbox"> ';
        echo esc_html($addon['title']);
        echo '</label>';

        // ✅ فقط کلاس‌ها - بدون استایل اینلاین
        echo '<div class="custom-addon-price-wrap">';
        if ($discount > 0) {
            echo '<span class="discount-badge">'.$discount.'%</span>';
            echo '<span class="original-price">'.wc_price($original_price).'</span>';
        }
        echo '<span class="final-price">+'.wc_price($final_price).'</span>';
        echo '</div>';

        echo '</div>';
    }
    echo '</div>';

    // ✅ جاوااسکریپت برای تغییر زنده قیمت
    ?>
    <script>
    jQuery(function($){
        var basePrice = <?php echo floatval($product->get_price()); ?>;
        var priceDisplay = $('.my-pricesj').first(); // 👈 مطمئن شو این کلاس توی قالب هست
        var bdi = priceDisplay.find('bdi');

        $('.addon-checkbox').on('change', function(){
            var totalExtra = 0;
            $('.addon-checkbox:checked').each(function(){
                totalExtra += parseFloat($(this).data('price'));
            });
            var newTotal = basePrice + totalExtra;
            if(bdi.length) {
                bdi.text(newTotal.toLocaleString() + ' تومان');
            } else {
                priceDisplay.html('<bdi>' + newTotal.toLocaleString() + ' تومان</bdi>');
            }
        });
    });
    </script>
    <?php
}

2. استایل (CSS)

حتما این CSS رو هم بذارید که استایل شیک باشه:

CSS
.custom-addon-price-wrap {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    text-align: left;
}

.custom-addon-price-wrap .original-price {
    font-size: 11px;
    color: #a0a0a0;
    text-decoration: line-through;
    opacity: 0.8;
}

.custom-addon-price-wrap .discount-line {
    display: flex;
    align-items: center;
    gap: 6px;
}

.custom-addon-price-wrap .discount-badge {
    background: #ffb700;
    color: #fff;
    font-size: 11px;
    padding: 2px 6px;
    border-radius: 4px;
    font-weight: bold;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 20px;
    min-width: 30px;
    text-align: center;
    line-height: 1;
}

.custom-addon-price-wrap .final-price {
    font-weight: bold;
    font-size: 14px;
    color: #555;
}

نکته مهم

  • برای تغییر قیمت به صورت زنده، یه کلاس به قیمت اصلی محصول بدید (مثلاً .my-pricesj) تا جاوااسکریپت راحت بتونه آپدیت کنه.
  • اگر قالب خاصی دارید و استایل متفاوت خواستید، می‌تونید CSS رو به سلیقه خودتون ویرایش کنید.

نمونه

Screenshot 2025 05 25 150706

Screenshot 2025 05 25 150638

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

اشتراک گذاری این مطلب
گفت‌وگو و پرسش‌ها

1 دیدگاه

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

پرسش یا تجربه خود را بنویسید. پاسخ شما پس از بررسی منتشر می‌شود.