Tạo variable product trong Woocommerce bằng PHP

Đây là bài hướng dẫn nâng cao dành cho các chuyên gia WordPress có kỹ năng lập trình PHP. Đây có lẽ là một trong những nhiệm vụ khó khăn nhất liên quan đến học WordPress với WooCommerce mà mình đã phải học trong vài năm.

Đoạn code dưới đây là một ví dụ điển hình về cách tạo sản phẩm dạng biến (variation/variable product), bạn sẽ học được gì:

  • Cách tạo plugin để nhập sản phẩm vào WordPress / WooCommerce
  • Cách tạo sản phẩm WooCommerce bằng mã PHP bên trong plugin hoặc giao diện WordPress.
  • Cách thêm thuộc tính vào sản phẩm bằng PHP.
  • Cách thêm các biến thể sản phẩm với PHP vào các sản phẩm WooCommerce của bạn.
  • Làm cách nào để kết hợp lại với nhau và tạo một plugin có khả năng tạo ra các sản phẩm variable cho WooCommerce với các kích cỡ và giá khác nhau cho mỗi loại sản phẩm.

Alt text

Đoạn code PHP:

/**
 * Plugin Name: Insert Variation Products - LayoutUp.com
 * Plugin URI: https://layoutup.com/
 * Description: Add a variable product with sizes to WP. Errors are written to wp-admin/insert_product_logs.txt file.
 * Version: 1.04
 * Author URI: https://layoutup.com/
 * License: GPL2
 */
 
//call addaprdct function when plugin is activated by admin:
register_activation_hook( __FILE__, 'addaprdct' );
 
function addaprdct(){
    global $wpdb;
    $cats = array(25);
    $insertLog = "insert_product_logs.txt";//name the log file in wp-admin folder
    $post = array(
         'post_title'   => "Product with Variations2",
         'post_content' => "product post content goes here…",
         'post_status'  => "publish",
         'post_excerpt' => "product excerpt content…",
         'post_name'    => "test_prod_vars2", //name/slug
         'post_type'    => "product"
    );
  
    //Create product/post:
    $new_post_id = wp_insert_post( $post, $wp_error );
    $logtxt = "PrdctID: $new_post_id\n";
 
    //make product type be variable:
    wp_set_object_terms ($new_post_id,'variable','product_type');
    //add category to product:
    wp_set_object_terms( $new_post_id, 25, 'product_cat');
 
    //################### Add size attributes to main product: ####################
    //Array for setting attributes
    $avail_attributes = array(
        '2xl',
        'xl',
        'lg',
        'md',
        'sm'
    );
    wp_set_object_terms($new_post_id, $avail_attributes, 'pa_size');
 
    $thedata = Array('pa_size'=>Array(
        'name'=>'pa_size',
        'value'=>'',
        'is_visible' => '1', 
        'is_variation' => '1',
        'is_taxonomy' => '1'
    ));
    update_post_meta( $new_post_id,'_product_attributes',$thedata);
    //########################## Done adding attributes to product #################
 
    //set product values:
    update_post_meta( $new_post_id, '_stock_status', 'instock');
    update_post_meta( $new_post_id, '_weight', "0.06" );
    update_post_meta( $new_post_id, '_sku', "skutest1");
    update_post_meta( $new_post_id, '_stock', "100" );
    update_post_meta( $new_post_id, '_visibility', 'visible' );
 
    //###################### Add Variation post types for sizes #############################
    //insert 5 variations post_types for 2xl, xl, lg, md, sm:
    $i=1;
    while ($i<=5) {//while creates 5 posts(1 for ea. size variation 2xl, xl etc):
        $my_post = array(
            'post_title'=> 'Variation #' . $i . ' of 5 for prdct#'. $new_post_id,
            'post_name' => 'product-' . $new_post_id . '-variation-' . $i,
            'post_status' => 'publish',
            'post_parent' => $new_post_id,//post is a child post of product post
            'post_type' => 'product_variation',//set post type to product_variation
            'guid'=>home_url() . '/?product_variation=product-' . $new_post_id . '-variation-' . $i
        );
 
        //Insert ea. post/variation into database:
        $attID = wp_insert_post( $my_post );
        $logtxt .= "Attribute inserted with ID: $attID\n";
        //set IDs for product_variation posts:
        $variation_id = $new_post_id + 1;
        $variation_two = $variation_id + 1;
        $variation_three = $variation_two + 1;
        $variation_four = $variation_three + 1;
        $variation_five = $variation_four + 1;
 
        //Create 2xl variation for ea product_variation:
        update_post_meta($variation_id, 'attribute_pa_size', '2xl');
        update_post_meta($variation_id, '_price', 21.99);
        update_post_meta($variation_id, '_regular_price', '21.99');
        //add size attributes to this variation:
        wp_set_object_terms($variation_id, $avail_attributes, 'pa_size');
        $thedata = Array('pa_size'=>Array(
            'name'=>'2xl',
            'value'=>'',
            'is_visible' => '1', 
            'is_variation' => '1',
            'is_taxonomy' => '1'
        ));
        update_post_meta( $variation_id,'_product_attributes',$thedata);
 
        //Create xl variation for ea product_variation:
        update_post_meta( $variation_two, 'attribute_pa_size', 'xl');
        update_post_meta( $variation_two, '_price', 20.99 );
        update_post_meta( $variation_two, '_regular_price', '20.99');
        //add size attributes:
        wp_set_object_terms($variation_two, $avail_attributes, 'pa_size');
        $thedata = Array('pa_size'=>Array(
            'name'=>'xl',
            'value'=>'',
            'is_visible' => '1', 
            'is_variation' => '1',
            'is_taxonomy' => '1'
        ));
        update_post_meta( $variation_two,'_product_attributes',$thedata);
         
        //Create lg variation for ea product_variation:
        update_post_meta( $variation_three, 'attribute_pa_size', 'lg');
        update_post_meta( $variation_three, '_price', 18.99 );
        update_post_meta( $variation_three, '_regular_price', '18.99');
        wp_set_object_terms($variation_three, $avail_attributes, 'pa_size');
        $thedata = Array('pa_size'=>Array(
            'name'=>'lg',
            'value'=>'',
            'is_visible' => '1', 
            'is_variation' => '1',
            'is_taxonomy' => '1'
        ));
        update_post_meta( $variation_three,'_product_attributes',$thedata);
 
        //Create md variation for ea product_variation:
        update_post_meta( $variation_four, 'attribute_pa_size', 'md');
        update_post_meta( $variation_four, '_price', 18.99 );
        update_post_meta( $variation_four, '_regular_price', '18.99');
        wp_set_object_terms($variation_four, $avail_attributes, 'pa_size');
        $thedata = Array('pa_size'=>Array(
            'name'=>'md',
            'value'=>'',
            'is_visible' => '1', 
            'is_variation' => '1',
            'is_taxonomy' => '1'
        ));
        update_post_meta( $variation_four,'_product_attributes',$thedata);
 
        //Create sm variation for ea product_variation:
        update_post_meta( $variation_five, 'attribute_pa_size', 'sm');
        update_post_meta( $variation_five, '_price', 18.99 );
        update_post_meta( $variation_five, '_regular_price', '18.99');
        wp_set_object_terms($variation_five, $avail_attributes, 'pa_size');
        $thedata = Array('pa_size'=>Array(
            'name'=>'sm',
            'value'=>'',
            'is_visible' => '1', 
            'is_variation' => '1',
            'is_taxonomy' => '1'
        ));
        update_post_meta( $variation_five,'_product_attributes',$thedata);
 
        $i++;
    }//end while i is less than or equal to 5(for 5 size variations)
    //############################ Done adding variation posts ############################
 
    //add product image:
    //require_once 'inc/add_pic.php';
    require_once(ABSPATH . 'wp-admin/includes/file.php');
    require_once(ABSPATH . 'wp-admin/includes/media.php');
    $thumb_url = "http://sportsweatherstats.com/pics/Logo.png";
 
    // Download file to temp location
    $tmp = download_url( $thumb_url );
 
    // Set variables for storage
    // fix file name for query strings
    preg_match('/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $thumb_url, $matches);
    $file_array['name'] = basename($matches[0]);
    $file_array['tmp_name'] = $tmp;
 
    // If error storing temporarily, unlink
    if ( is_wp_error( $tmp ) ) {
        @unlink($file_array['tmp_name']);
        $file_array['tmp_name'] = '';
        $logtxt .= "Error: download_url error – $tmp\n";
    }else{
        $logtxt .= "download_url: $tmp\n";
    }
 
    //use media_handle_sideload to upload img:
    $thumbid = media_handle_sideload( $file_array, $new_post_id, 'gallery desc' );
    // If error storing permanently, unlink
    if ( is_wp_error($thumbid) ) {
        @unlink($file_array['tmp_name']);
        //return $thumbid;
        $logtxt .= "Error: media_handle_sideload error – $thumbid\n";
    }else{
        $logtxt .= "ThumbID: $thumbid\n";
    }
 
    set_post_thumbnail($new_post_id, $thumbid);
 
    //optionally add second image:
    require_once(ABSPATH . "wp-admin" . '/includes/image.php');
    $thumb_url2 = "http://sportsweatherstats.com/pics/NFLpredict.png";
    // Download file to temp location
    $tmp2 = download_url( $thumb_url2 );
    $logtxt .= "download_url2: $tmp2\n";
    // fix file name for query strings
    preg_match('/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $thumb_url2, $matches);
    $file_array2['name'] = basename($matches[0]);
    $file_array2['tmp_name'] = $tmp2;
    $imgID = media_handle_sideload( $file_array2, $new_post_id, 'desc' );
    $logtxt .= "ThumbID2: $imgID\n";
    update_post_meta( $new_post_id, '_product_image_gallery', $imgID);
 
    //append to log file(file shows up in wp-admin folder):
    $fh2 = fopen($insertLog, 'a') or die("can't open log file to append");
    fwrite($fh2, $logtxt);
    fclose($fh2);
 
}//end addaprdct function

Giải thích

Mỗi dòng lệnh có comment rõ ràng để các bạn hiểu về từng đoạn code. Phần bắt buộc duy nhất của phần bình luận là tên plugin. Đơn giản chỉ cần sửa đổi mã để phù hợp với nhu cầu của bạn nếu bạn đang sử dụng mã này làm công cụ ban đầu khi viết plugin WordPress mới hoặc để nguyên như vậy cũng có thể sử dụng được ngay nếu bạn muốn. Đây không phải là một plugin thương mại, nó chỉ dành cho các nhà phát triển WordPress.

Để kích hoạt, mình có sử dụng WordPress hooks với register_activation_hook, hàm này sẽ thực thi khi plugin được kích hoạt. Điều đó có nghĩa là sau khi bạn cài đặt plugin này, sản phẩm trong ví dụ này sẽ được tạo ra khi bạn kích hoạt plugin từ trang plugin.


Bạn nên xem