Multi Select fields in Woocommerce backend

亡梦爱人 提交于 2019-12-20 02:14:03

问题


I am trying to create 4 multi-select options at Woocommerce product variations.

For example: I am selling trees and want to display the season the tree is available. So we have 4 seasons (spring, summer, autumn, winter), Some trees are available in two or tree seasons.

I added this code to my functions.php, but it won't save the selected options. When i save the option and reload the page the options are blank again.

And I was also wondering how to show the selected options on the single product page (frontend) as icon.

For now the function with the options works at the product variations. Please see this screenshot (product variation with multi select options):

My code:

// Add Variation Settings
add_action( 'woocommerce_product_after_variable_attributes', 'variation_settings_fields', 10, 3 );

/**
 * Create custom field type
 *
*/
function woocommerce_wp_select_multiple( $field ) {
    global $thepostid, $post, $woocommerce;

    $thepostid              = empty( $thepostid ) ? $post->ID : $thepostid;
    $field['class']         = isset( $field['class'] ) ? $field['class'] : 'select short';
    $field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
    $field['name']          = isset( $field['name'] ) ? $field['name'] : $field['id'];
    $field['value']         = isset( $field['value'] ) ? $field['value'] : ( get_post_meta( $thepostid, $field['id'], true ) ? get_post_meta( $thepostid, $field['id'], true ) : array() );

    echo '<p class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '"><label for="' . esc_attr( $field['id'] ) . '">' . wp_kses_post( $field['label'] ) . '</label><select id="' . esc_attr( $field['id'] ) . '" name="' . esc_attr( $field['name'] ) . '" class="' . esc_attr( $field['class'] ) . '" multiple="multiple">';

    foreach ( $field['options'] as $key => $value ) {

        echo '<option value="' . esc_attr( $key ) . '" ' . ( in_array( $key, $field['value'] ) ? 'selected="selected"' : '' ) . '>' . esc_html( $value ) . '</option>';

    }

    echo '</select> ';

    if ( ! empty( $field['description'] ) ) {

        if ( isset( $field['desc_tip'] ) && false !== $field['desc_tip'] ) {
            echo '<img class="help_tip" data-tip="' . esc_attr( $field['description'] ) . '" src="' . esc_url( WC()->plugin_url() ) . '/assets/images/help.png" height="16" width="16" />';
        } else {
            echo '<span class="description">' . wp_kses_post( $field['description'] ) . '</span>';
        }

    }
    echo '</p>';
}


/**
 * Create new fields for variations
 *
*/
function variation_settings_fields( $loop, $variation_data, $variation ) {

    woocommerce_wp_select_multiple( array(
        'id' => 'season_' . $variation->ID,
        'class' => 'season',
        'label' => __('Season', 'woocommerce'),
        'value' => get_post_meta( $variation->ID, '_season', true ),
        'options' => array(
            'spring' => 'Spring',
            'summer' => 'Summer',
            'autumn' => 'Autumn',
            'winter' => 'Winter',
        ))
    );
}

add_action( 'woocommerce_save_product_variation', 'save_variation_settings_fields', 10, 2 );
function save_variation_settings_fields( $post_id ) {

    $select = $_POST["season_$post_id"];
    if( ! empty( $select ) ) {
        update_post_meta( $post_id, '_season', esc_attr( $select ) );
    }
}   

回答1:


To handle variable products for multi select fields is another thing and some changes need to be done to make it work. I have maid 2 answers after below:

  1. The first one for product variations (for you)
  2. The other one for all other product types

So the main function that enable multi-select fields in Woocommerce backend will be:

function woocommerce_wp_multi_select( $field, $variation_id = 0 ) {
    global $thepostid, $post;

    if( $variation_id == 0 )
        $the_id = empty( $thepostid ) ? $post->ID : $thepostid;
    else
        $the_id = $variation_id;

    $field['class']         = isset( $field['class'] ) ? $field['class'] : 'select short';
    $field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
    $field['name']          = isset( $field['name'] ) ? $field['name'] : $field['id'];

    $meta_data              = maybe_unserialize( get_post_meta( $the_id, $field['id'], true ) );
    $meta_data              = $meta_data ? $meta_data : array() ;

    $field['value'] = isset( $field['value'] ) ? $field['value'] : $meta_data;

    echo '<p class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '"><label for="' . esc_attr( $field['id'] ) . '">' . wp_kses_post( $field['label'] ) . '</label><select id="' . esc_attr( $field['id'] ) . '" name="' . esc_attr( $field['name'] ) . '" class="' . esc_attr( $field['class'] ) . '" multiple="multiple">';

    foreach ( $field['options'] as $key => $value ) {
        echo '<option value="' . esc_attr( $key ) . '" ' . ( in_array( $key, $field['value'] ) ? 'selected="selected"' : '' ) . '>' . esc_html( $value ) . '</option>';
    }
    echo '</select> ';
    if ( ! empty( $field['description'] ) ) {
        if ( isset( $field['desc_tip'] ) && false !== $field['desc_tip'] ) {
            echo '<img class="help_tip" data-tip="' . esc_attr( $field['description'] ) . '" src="' . esc_url( WC()->plugin_url() ) . '/assets/images/help.png" height="16" width="16" />';
        } else {
            echo '<span class="description">' . wp_kses_post( $field['description'] ) . '</span>';
        }
    }
}

Code goes in function.php file of your active child theme (or active theme). This function, will handle now any type of products, including product variations.


1) For product variations (for you):

// Add custom multi-select fields in variation setting tab
add_action( 'woocommerce_product_after_variable_attributes', 'add_variation_settings_fields', 20, 3 );
function add_variation_settings_fields( $loop, $variation_data, $variation_post ) {

    woocommerce_wp_multi_select( array(
        'id' => '_season',
        'name' => '_season['.$loop.'][]',
        'class' => '',
        'label' => __('Season', 'woocommerce'),
        'options' => array(
            'spring' => __("Spring", "woocommerce"),
            'summer' => __("Summer", "woocommerce"),
            'autumn' => __("Autumn", "woocommerce"),
            'winter' => __("Winter", "woocommerce"),
        )
    ), $variation_post->ID );
}

// Save custom multi-select fields for variations
add_action( 'woocommerce_save_product_variation', 'save_variation_settings_fields', 10, 2 );
function save_variation_settings_fields( $variation_id, $i ) {
    if( isset( $_POST['_season'][$i] ) ){
        $post_data = $_POST['_season'][$i];
        // Multi data sanitization 
        $sanitize_data = array();
        if( is_array($post_data) && sizeof($post_data) > 0 ){
            foreach( $post_data as $value ){
                $sanitize_data[] = esc_attr( $value );
            }
        }
        update_post_meta( $variation_id, '_season', $sanitize_data );
    }

}

Code goes in function.php file of your active child theme (or active theme). Tested and works.



2) For all other product types (except product variations, where we hide that custom field):

// Add custom fields for product general option settings (hidding it for variable products)
add_action( 'woocommerce_product_options_general_product_data', 'add_custom_settings_fields', 20 );
function add_custom_settings_fields() {
    global $post;

    echo '<div class="options_group hide_if_variable"">'; // Hidding in variable products

    woocommerce_wp_multi_select( array(
        'id' => '_season',
        'name' => '_season[]',
        'class' => '',
        'label' => __('Season', 'woocommerce'),
        'options' => array(
            'spring' => __("Spring", "woocommerce"),
            'summer' => __("Summer", "woocommerce"),
            'autumn' => __("Autumn", "woocommerce"),
            'winter' => __("Winter", "woocommerce"),
        )
    ) );

    echo '</div>';
}

// Save custom multi-select fields to database when submitted in Backend (for all other product types)
add_action( 'woocommerce_process_product_meta', 'save_product_options_custom_fields', 30, 1 );
function save_product_options_custom_fields( $post_id ){
    if( isset( $_POST['_season'] ) ){
        $post_data = $_POST['_season'];
        // Multi data sanitization 
        $sanitize_data = array();
        if( is_array($post_data) && sizeof($post_data) > 0 ){
            foreach( $post_data as $value ){
                $sanitize_data[] = esc_attr( $value );
            }
        }
        update_post_meta( $post_id, '_season', $sanitize_data );
    }
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.



来源:https://stackoverflow.com/questions/50132928/multi-select-fields-in-woocommerce-backend

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!