phpwoocommercemulti-selecttaxonomy-termsproduct-variations

Add product variation multi select category field and save to database


I'm new to this. I managed to add a field in the product variations and to select the category code and to save this into the database and it works. But the saved value is formatted in the database like: a:2:{i:0;s:9:"cat1";i:1;s:32:"cat2";}. I don't know how to get this data and to use it back properly in the multi-select field, showing the selected values that have been saved.

Can somebody help me, either to save the data like "cat1,cat2,..." or help me to display the data as readable plain text.

Here is my code:

// Variation Categories.
add_action( 'woocommerce_variation_options_pricing', 'woo_add_variation_category',11,2 );
function woo_add_variation_category() {
    global $variation;
    //dropdown category (4lines)
    $taxonomy = 'product_cat';
    $orderby = 'name';
    $show_count = 0;      // 1 for yes, 0 for no
    $pad_counts = 0;      // 1 for yes, 0 for no
    $hierarchical = 1;      // 1 for yes, 0 for no  
    $title = '';
    $empty = false;
    $childof = 8821;

    $args = array(
        'taxonomy' => $taxonomy,
        'orderby' => $orderby,
        'show_count' => $show_count,
        'pad_counts' => $pad_counts,
        'hierarchical' => $hierarchical,
        'title_li' => $title,
        'hide_empty' => $empty,
        'child_of' => $childof, 
    );

    $product_categories = get_terms( 'product_cat', $args );
    
    echo '<select class="js-example-basic-multiple" name="var_cat[]" multiple="multiple">';

    foreach( $product_categories as $category ){
        echo "<option value = '" . esc_attr( $category->name ) . "'  >" . esc_html( $category->name ) ."</option>";
    }

    echo "</select><br/>";
}   
    
add_action( 'woocommerce_save_product_variation', 'save_product_category_variation', 11, 2 );
function save_product_category_variation( $variation_id, $loop ) { 
    if( isset( $_POST['var_cat'] ) ) { 
        update_post_meta($variation_id, '_variation_category', array_map( 'strip_tags', $_POST['var_cat'] ) );
    }
}

Solution

  • In WordPress database, array values are always serialized.

    There are unnecessary and missing things in your code, try the following revised code instead:

    add_action( 'woocommerce_variation_options_pricing', 'add_variation_custom_setting_field', 10, 3 );
    function add_variation_custom_setting_field( $loop, $variation_data, $variation ) {
        $variation_object  = wc_get_product($variation->ID); // Variation product object
        $selected_term_ids = (array) $variation_object->get_meta('category_ids'); // Get the field select values (array)
    
        $category_terms    = get_terms( array(
            'taxonomy'      => 'product_cat',
            'hide_empty'    => false,
            'child_of'      => 8821, 
        ) );
    
        echo '<div> <p class="form-row form-row-first"><label>'.__('Categories', 'woocommerce').'</label>
        <select class="js-example-basic-multiple" name="variation_cats_'.$loop.'[]" multiple="multiple">';
    
        foreach( $category_terms as $term ){
            $selected = in_array($term->term_id, $selected_term_ids) ? ' selected' : '';
            printf('<option value="%s"%s>%s</option>', esc_attr($term->term_id), $selected, esc_html($term->name));
        }
    
        echo "</p></select></div>";
    }   
    
    add_action('woocommerce_admin_process_variation_object', 'save_variation_custom_setting_field', 10, 2 );
    function save_variation_custom_setting_field( $variation, $i ) { 
        $category_ids = isset($_POST['variation_cats_'.$i]) ? array_map('intval', (array) wp_unslash($_POST['variation_cats_'.$i])) : array();
    
        $variation->update_meta_data('category_ids', $category_ids );
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). It should work as expected now.