📦 فصل ۲: مدیریت پیشرفته محصولات
قلب هر فروشگاه، محصولاتش هستند. ووکامرس انواع مختلف محصول را پشتیبانی میکند و در این فصل از محصول ساده تا محصول متغیر، گروهی، خارجی، دانلودی و ساخت ویژگیهای سفارشی پیش میرویم. مثالهای واقعی از صنعت فرش (ICSD) ارائه میشود.
قلب هر فروشگاه، محصولاتش هستند. ووکامرس انواع مختلف محصول را پشتیبانی میکند و در این فصل از محصول ساده تا محصول متغیر، گروهی، خارجی، دانلودی و ساخت ویژگیهای سفارشی پیش میرویم. مثالهای واقعی از صنعت فرش (ICSD) ارائه میشود.
📑 سرفصلهای این فصل
۱. انواع محصول در ووکامرس
| نوع | کاربرد | مثال |
|---|---|---|
| Simple | محصول ساده با یک قیمت | کتاب، لپتاپ، فرش با ابعاد ثابت |
| Variable | محصول با چند نسخه | پیراهن (سایز/رنگ)، فرش (ابعاد متفاوت) |
| Grouped | چند محصول مرتبط | پک نوشتافزار (دفتر + قلم + تراش) |
| External | لینک به فروشگاه دیگر | افیلیت دیجیکالا/Amazon |
| Virtual | محصول غیرفیزیکی | مشاوره، آموزش حضوری |
| Downloadable | قابل دانلود | کتاب الکترونیکی، نرمافزار، تم |
۲. محصول ساده
سادهترین نوع محصول. مدیریت موجودی، قیمت و ویژگیهای پایه.
نکات کلیدی
- SKU: کد یکتای محصول – برای انبارداری ضروری
- Regular Price / Sale Price: قیمت اصلی و تخفیفی
- Stock Management: مدیریت موجودی فعال شود
- Weight & Dimensions: برای محاسبه هزینه ارسال
ساخت محصول با کد
function icsd_create_simple_product() {
$product = new WC_Product_Simple();
$product->set_name( 'فرش دستباف کاشان ۲×۳ متری' );
$product->set_slug( 'kashan-handmade-carpet-2x3' );
$product->set_status( 'publish' );
$product->set_catalog_visibility( 'visible' );
$product->set_description( 'فرش دستباف ابریشم کاشان با طرح لچک ترنج...' );
$product->set_short_description( 'فرش دستباف اصیل کاشان' );
$product->set_sku( 'CARPET-KSH-2X3-001' );
$product->set_regular_price( '15000000' );
$product->set_sale_price( '13500000' );
$product->set_manage_stock( true );
$product->set_stock_quantity( 5 );
$product->set_stock_status( 'instock' );
$product->set_weight( '8' ); // کیلوگرم
$product->set_length( '300' ); // سانتیمتر
$product->set_width( '200' );
$product->set_height( '2' );
// دستهبندی
$product->set_category_ids( [ 12, 15 ] ); // ID دستهها
// تگ
$product->set_tag_ids( [ 8, 22 ] );
// تصویر شاخص
$product->set_image_id( 245 );
$product->set_gallery_image_ids( [ 246, 247, 248 ] );
$product_id = $product->save();
return $product_id;
}
۳. محصول متغیر (مهمترین نوع) ⭐
محصول متغیر یعنی یک محصول با چندین واریشن (نسخه)؛ هر واریشن قیمت، موجودی، تصویر و SKU جداگانه دارد.
مرحله ۱: تعریف ویژگیها (Attributes)
ابتدا در Products → Attributes ویژگی «ابعاد» را تعریف کنید:
Name: ابعاد
Slug: pa_size
Enable Archives: ✓
Default sort order: Custom ordering
سپس مقادیر:
- ۱.۵ × ۱ متر (slug: 1-5x1)
- ۲ × ۳ متر (slug: 2x3)
- ۳ × ۴ متر (slug: 3x4)
- ۴ × ۶ متر (slug: 4x6)
مرحله ۲: ساخت محصول متغیر با کد
function icsd_create_variable_carpet() {
// 1. ساخت محصول والد
$product = new WC_Product_Variable();
$product->set_name( 'فرش ماشینی ۷۰۰ شانه طرح ترنج' );
$product->set_status( 'publish' );
$product->set_sku( 'CARPET-700-TARANJ' );
$product->set_description( 'فرش ماشینی با کیفیت اکریلیک ۷۰۰ شانه...' );
// 2. تعریف ویژگیها
$attribute = new WC_Product_Attribute();
$attribute->set_id( wc_attribute_taxonomy_id_by_name( 'pa_size' ) );
$attribute->set_name( 'pa_size' );
$attribute->set_options( [
get_term_by('slug', '1-5x1', 'pa_size')->term_id,
get_term_by('slug', '2x3', 'pa_size')->term_id,
get_term_by('slug', '3x4', 'pa_size')->term_id,
get_term_by('slug', '4x6', 'pa_size')->term_id,
] );
$attribute->set_position( 0 );
$attribute->set_visible( true );
$attribute->set_variation( true ); // مهم!
$product->set_attributes( [ $attribute ] );
$product_id = $product->save();
// 3. ساخت واریشنها
$variations = [
[ 'size' => '1-5x1', 'price' => 1500000, 'sku' => 'CARPET-700-1-5X1', 'stock' => 10 ],
[ 'size' => '2x3', 'price' => 4500000, 'sku' => 'CARPET-700-2X3', 'stock' => 8 ],
[ 'size' => '3x4', 'price' => 9000000, 'sku' => 'CARPET-700-3X4', 'stock' => 5 ],
[ 'size' => '4x6', 'price' => 18000000,'sku' => 'CARPET-700-4X6', 'stock' => 3 ],
];
foreach ( $variations as $var_data ) {
$variation = new WC_Product_Variation();
$variation->set_parent_id( $product_id );
$variation->set_attributes( [ 'pa_size' => $var_data['size'] ] );
$variation->set_regular_price( $var_data['price'] );
$variation->set_sku( $var_data['sku'] );
$variation->set_manage_stock( true );
$variation->set_stock_quantity( $var_data['stock'] );
$variation->set_stock_status( 'instock' );
$variation->save();
}
// 4. بهروزرسانی محصول والد
WC_Product_Variable::sync( $product_id );
return $product_id;
}
دریافت تمام واریشنهای یک محصول
function icsd_get_product_variations( $product_id ) {
$product = wc_get_product( $product_id );
if ( ! $product || ! $product->is_type( 'variable' ) ) {
return [];
}
$variations = [];
foreach ( $product->get_children() as $variation_id ) {
$variation = wc_get_product( $variation_id );
$variations[] = [
'id' => $variation_id,
'sku' => $variation->get_sku(),
'price' => $variation->get_price(),
'stock' => $variation->get_stock_quantity(),
'attributes' => $variation->get_variation_attributes(),
'image' => wp_get_attachment_url( $variation->get_image_id() ),
];
}
return $variations;
}
۴. محصول گروهی
محصول گروهی، چند محصول ساده را به عنوان یک «گروه» نمایش میدهد. مثلاً پک «فرش + پاندا + کاور» – مشتری میتواند هر کدام را جداگانه به سبد اضافه کند.
function icsd_create_grouped_product( $children_ids ) {
$product = new WC_Product_Grouped();
$product->set_name( 'پک کامل لوازم دفتری' );
$product->set_status( 'publish' );
$product->set_sku( 'OFFICE-PACK-001' );
$product->set_children( $children_ids ); // آرایه ID محصولات ساده
return $product->save();
}
// استفاده:
icsd_create_grouped_product( [ 100, 101, 102, 103 ] );
۵. محصول خارجی (Affiliate)
محصول خارجی به جای دکمه «افزودن به سبد»، دکمه «خرید از فروشگاه فروشنده» نمایش میدهد و لینک به سایت دیگر میدهد.
$product = new WC_Product_External();
$product->set_name( 'لپتاپ ASUS - خرید از دیجیکالا' );
$product->set_regular_price( '45000000' );
$product->set_product_url( 'https://www.digikala.com/product/dkp-12345?aff=icsd' );
$product->set_button_text( 'خرید از دیجیکالا' );
$product->save();
۶. محصولات مجازی و دانلودی
محصول مجازی (Virtual)
محصولی که نیاز به ارسال فیزیکی ندارد (مثل مشاوره، خدمات، عضویت).
محصول دانلودی (Downloadable)
$product = new WC_Product_Simple();
$product->set_name( 'کتاب الکترونیکی هنر فرشبافی کاشان' );
$product->set_regular_price( '85000' );
$product->set_virtual( true );
$product->set_downloadable( true );
// تنظیم فایل دانلودی
$downloads = [];
$download = new WC_Product_Download();
$download->set_id( wp_generate_uuid4() );
$download->set_name( 'فایل PDF' );
$download->set_file( 'https://icsd.ir/downloads/secure/carpet-art.pdf' );
$downloads[] = $download;
$product->set_downloads( $downloads );
$product->set_download_limit( 3 ); // حداکثر ۳ بار دانلود
$product->set_download_expiry( 30 ); // اعتبار ۳۰ روز
$product->save();
public_html نگه دارید و از X-Sendfile یا تنظیمات WooCommerce برای جلوگیری از دانلود مستقیم استفاده کنید. تنظیمات: WooCommerce → Settings → Products → Downloadable products → File download method: Force downloads.
۷. ویژگیها و واریشنها
دو نوع ویژگی
| نوع | کاربرد | قابل استفاده در واریشن |
|---|---|---|
| Global Attribute | قابل استفاده در چندین محصول (پیشنهادی) | بله ✓ |
| Custom Attribute | فقط برای یک محصول | بله، اما توصیه نمیشود |
ساخت Global Attribute با کد
function icsd_register_attribute( $name, $slug ) {
if ( wc_attribute_taxonomy_id_by_name( $slug ) ) {
return; // قبلاً ثبت شده
}
$args = [
'attribute_label' => $name,
'attribute_name' => $slug,
'attribute_type' => 'select',
'attribute_orderby' => 'menu_order',
'attribute_public' => 1,
];
wc_create_attribute( $args );
// ثبت taxonomy
register_taxonomy( 'pa_' . $slug, 'product', [
'hierarchical' => false,
'show_ui' => false,
'query_var' => true,
'rewrite' => false,
]);
}
// استفاده
icsd_register_attribute( 'جنس', 'material' );
icsd_register_attribute( 'تعداد رج', 'rajshomar' );
// افزودن مقادیر
wp_insert_term( 'ابریشم', 'pa_material' );
wp_insert_term( 'پشم', 'pa_material' );
wp_insert_term( 'اکریلیک', 'pa_material' );
wp_insert_term( '۷۰۰ شانه', 'pa_rajshomar' );
wp_insert_term( '۱۲۰۰ شانه', 'pa_rajshomar' );
۸. فیلدهای سفارشی محصول
گاهی نیاز به فیلدهای اختصاصی دارید که در WooCommerce نیست؛ مثل «تاریخ تولید»، «گارانتی»، «شناسه بافنده» (برای فرش).
روش ۱: استفاده از ACF (سریعترین)
افزونه Advanced Custom Fields را نصب کنید، سپس Custom Fields → Add New Field Group با Location: Post Type = Product.
روش ۲: کد سفارشی برای متاباکس
<?php
class ICSD_Product_Custom_Fields {
public function __construct() {
// افزودن تب در ادیتور محصول
add_filter( 'woocommerce_product_data_tabs', [ $this, 'add_tab' ] );
add_action( 'woocommerce_product_data_panels', [ $this, 'add_panel' ] );
add_action( 'woocommerce_process_product_meta', [ $this, 'save_fields' ] );
}
public function add_tab( $tabs ) {
$tabs['icsd_carpet'] = [
'label' => 'اطلاعات فرش',
'target' => 'icsd_carpet_data',
'class' => [ 'show_if_simple', 'show_if_variable' ],
'priority' => 21,
];
return $tabs;
}
public function add_panel() {
global $post;
?>
'sanitize_text_field',
'_icsd_origin' => 'sanitize_key',
'_icsd_knots_per_meter' => 'absint',
'_icsd_design_story' => 'sanitize_textarea_field',
];
foreach ( $fields as $key => $sanitizer ) {
if ( isset( $_POST[ $key ] ) ) {
$value = call_user_func( $sanitizer, wp_unslash( $_POST[ $key ] ) );
update_post_meta( $post_id, $key, $value );
}
}
}
}
new ICSD_Product_Custom_Fields();
نمایش فیلدها در صفحه محصول
add_action( 'woocommerce_single_product_summary', 'icsd_show_carpet_info', 25 );
function icsd_show_carpet_info() {
global $product;
$weaver = get_post_meta( $product->get_id(), '_icsd_weaver_name', true );
$origin = get_post_meta( $product->get_id(), '_icsd_origin', true );
$knots = get_post_meta( $product->get_id(), '_icsd_knots_per_meter', true );
if ( ! $weaver && ! $origin ) {
return;
}
echo '';
if ( $weaver ) echo 'بافنده: ' . esc_html( $weaver ) . '
';
if ( $origin ) echo 'اصالت: ' . esc_html( $origin ) . '
';
if ( $knots ) echo 'گره در متر: ' . number_format( $knots ) . '
';
echo '';
}
۹. ورود انبوه محصولات با CSV
ووکامرس import/export داخلی دارد ولی برای حجم بالا، اسکریپت اختصاصی بهتر است.
function icsd_bulk_import_products( $csv_file ) {
if ( ! file_exists( $csv_file ) ) {
return new WP_Error( 'no_file', 'فایل پیدا نشد' );
}
$imported = 0;
$errors = [];
$handle = fopen( $csv_file, 'r' );
$headers = fgetcsv( $handle ); // اولین ردیف = هدر
while ( ( $row = fgetcsv( $handle ) ) !== false ) {
$data = array_combine( $headers, $row );
try {
$product = new WC_Product_Simple();
$product->set_name( $data['name'] );
$product->set_sku( $data['sku'] );
$product->set_regular_price( $data['price'] );
$product->set_description( $data['description'] );
$product->set_stock_quantity( (int) $data['stock'] );
$product->set_manage_stock( true );
$product->set_status( 'publish' );
// دستهبندی
if ( ! empty( $data['category'] ) ) {
$term = get_term_by( 'name', $data['category'], 'product_cat' );
if ( $term ) {
$product->set_category_ids( [ $term->term_id ] );
}
}
$product->save();
$imported++;
} catch ( Exception $e ) {
$errors[] = "خطا در سطر {$imported}: " . $e->getMessage();
}
}
fclose( $handle );
return [
'imported' => $imported,
'errors' => $errors,
];
}
// اجرا با WP-CLI
// wp eval-file bulk-import.php
📝 مثالهای عملی
🟢 آسان: تخفیف خودکار محصولات یک دسته
function icsd_apply_category_discount( $category_slug, $discount_percent ) {
$args = [
'post_type' => 'product',
'posts_per_page' => -1,
'tax_query' => [
[
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $category_slug,
],
],
];
$query = new WP_Query( $args );
while ( $query->have_posts() ) {
$query->the_post();
$product = wc_get_product( get_the_ID() );
$regular = (float) $product->get_regular_price();
$sale = $regular * ( 1 - $discount_percent / 100 );
$product->set_sale_price( round( $sale ) );
$product->save();
}
wp_reset_postdata();
}
// تخفیف ۲۰٪ روی فرشهای ماشینی
icsd_apply_category_discount( 'machine-carpet', 20 );
🟡 متوسط: محاسبه قیمت بر اساس متراژ (فرش متراژی)
// افزودن فیلد متراژ به صفحه محصول
add_action( 'woocommerce_before_add_to_cart_button', 'icsd_add_meter_field' );
function icsd_add_meter_field() {
global $product;
if ( ! has_term( 'meter-carpet', 'product_cat', $product->get_id() ) ) {
return;
}
?>
قیمت هر متر: get_price() ); ?>
get_cart() as $cart_item ) {
if ( ! isset( $cart_item['icsd_meter'] ) ) continue;
$base_price = $cart_item['data']->get_regular_price();
$new_price = $base_price * $cart_item['icsd_meter'];
$cart_item['data']->set_price( $new_price );
}
}
🔴 پیشرفته: محصول دینامیک با تنظیمات دلخواه
/**
* محصول سفارشی فرش با گزینههای شخصیسازی
* - انتخاب رنگ زمینه
* - انتخاب طرح حاشیه
* - حک نام مشتری روی برچسب
*/
class ICSD_Customizable_Carpet {
public function __construct() {
add_action( 'woocommerce_before_add_to_cart_button', [ $this, 'render_options' ] );
add_filter( 'woocommerce_add_cart_item_data', [ $this, 'save_options' ], 10, 2 );
add_filter( 'woocommerce_get_item_data', [ $this, 'display_options' ], 10, 2 );
add_action( 'woocommerce_checkout_create_order_line_item', [ $this, 'save_to_order' ], 10, 4 );
add_action( 'woocommerce_before_calculate_totals', [ $this, 'apply_custom_price' ] );
}
public function render_options() {
global $product;
if ( ! $product->is_type( 'simple' ) ) return;
if ( ! get_post_meta( $product->get_id(), '_is_customizable', true ) ) return;
?>
'کرم', 'navy' => 'سرمهای', 'red' => 'قرمز' ];
if ( ! empty( $cart_item['bg_color'] ) ) {
$item_data[] = [
'name' => 'رنگ زمینه',
'value' => $color_labels[ $cart_item['bg_color'] ] ?? '',
];
}
if ( ! empty( $cart_item['custom_text'] ) ) {
$item_data[] = [
'name' => 'متن سفارشی',
'value' => $cart_item['custom_text'],
];
}
return $item_data;
}
public function apply_custom_price( $cart ) {
$color_extra = [ 'cream' => 0, 'navy' => 500000, 'red' => 800000 ];
foreach ( $cart->get_cart() as $cart_item ) {
if ( empty( $cart_item['bg_color'] ) ) continue;
$base = $cart_item['data']->get_regular_price();
$extra = $color_extra[ $cart_item['bg_color'] ] ?? 0;
// اگر متن سفارشی هم خواست
if ( ! empty( $cart_item['custom_text'] ) ) {
$extra += 200000;
}
$cart_item['data']->set_price( $base + $extra );
}
}
public function save_to_order( $item, $cart_item_key, $values, $order ) {
if ( ! empty( $values['bg_color'] ) ) {
$item->add_meta_data( 'رنگ زمینه', $values['bg_color'] );
}
if ( ! empty( $values['custom_text'] ) ) {
$item->add_meta_data( 'متن سفارشی', $values['custom_text'] );
}
}
}
new ICSD_Customizable_Carpet();
📌 خلاصه فصل
- ✅ ۶ نوع محصول در ووکامرس وجود دارد – Variable پرکاربردترین برای صنعت ایران
- ✅ همیشه از Global Attribute به جای Custom Attribute استفاده کنید (قابل reuse)
- ✅ HPOS-compatible کد بنویسید: همیشه از
wc_get_product()و CRUD - ✅ برای فیلدهای سفارشی: ACF برای سرعت، متاباکس کدنویسی برای انعطاف
- ✅ برای واردات انبوه از CSV استفاده کنید + اسکریپت سفارشی برای اعتبارسنجی
- ✅ از
woocommerce_before_calculate_totalsبرای قیمتگذاری دینامیک استفاده کنید