How to add Custom Description field in Shipping methods (Backend)

Viewed 6338

I want to add a custom field in Shipping Zone page under shipping method, it will be a text input, the user will able to add a custom message and I'll show that message in the front end.

I noticed it saves the data in wp_woocommerce_shipping_zone_methods table which doesn't have any extra column to save the data; so I think I have to use my custom logic, but I don't know the name of the hook(s).

So my question is, is there is any hook which will help/allow me

  1. To add a custom field.
  2. To add a custom column.

TL;DR: enter image description here

enter image description here

4 Answers
add_action('woocommerce_init', 'shipping_instance_form_fields_filters');

function shipping_instance_form_fields_filters()
{
    $shipping_methods = WC()->shipping->get_shipping_methods();
    foreach($shipping_methods as $shipping_method) {
        add_filter('woocommerce_shipping_instance_form_fields_' . $shipping_method->id, 'shipping_instance_form_add_extra_fields');
    }
}

function shipping_instance_form_add_extra_fields($settings)
{
    $settings['shipping_extra_field'] = [
        'title' => 'Shipping extra field',
        'type' => 'text', 
        'placeholder' => 'shipping',
        'description' => ''
    ];

    return $settings;
} 

Thanks @Wprog_dy for idea, but your code only adds field to the 'flat_rate' shipping method and your function is really weirdly complicated.

My example will add a custom field to all shipping methods

this is how I implemented the custom description field in shipping methods with flat rate and free shipping

My function.php file:

add_filter( 'woocommerce_shipping_instance_form_fields_flat_rate', array( $this, 'add_extra_fields_in_flat_rate' ), 10, 1);
public function add_extra_fields_in_flat_rate($settings)
    {
        $counter = 0;
        $arr = array();
        foreach ($settings as $key => $value) <br>
        {
            if($key=='cost' && $counter==0)
            {
                $arr[$key] = $value; 
                $arr['shipping_extra_field'] = array(
                    'title'         => __( 'Shipping Extra Field', 'woocommerce' ), 
                    'type'             => 'text', 
                    'placeholder'    => 'shipping',
                    'description'    => ''
                ); 
                $counter++; 
            } 
            else 
            {
                $arr[$key] = $value;
            } 
        }
        return $arr; 
    } 

Matic Jan did excelent job and answered this question, but if you can add custom field to any shipping method ... then how do you "use" its content at the checkout page? Here is a code I use, hooking to woocommerce_after_shipping_rate.

function shipping_instance_custom_desc( $shipping_rate, $index ) {
    
if( is_cart() ) return; // Exit on cart page
            
    $current_instance_ids = WC()->session->get( 'chosen_shipping_methods' );
    $current_instance_id = $current_instance_ids[0];
        
    if( $shipping_rate->id == $current_instance_id ) {
        
        $option_key = 'woocommerce_'.$shipping_rate->method_id.'_'.$shipping_rate->instance_id.'_settings';
        
        $instance_settings = get_option( $option_key );
        
        if( isset( $instance_settings[ 'shipping_extra_field' ] ) ) {
            
            ?>
            <div class="shipping-method-desc">
                <?php echo $instance_settings[ 'shipping_extra_field' ] ?>
            </div>
            <?php
            
        }
        
    }
    
}
add_action( 'woocommerce_after_shipping_rate', 'shipping_instance_custom_desc' , 10, 2 );

I hoped there will be some wc_ function to get shipping method instance settings, but oh boy was I wrong ... I found out shipping method instance settings are stored in wp_options table as any other WP settings. So my code gets this option value and check if it has custom field ( shipping_extra_field, same as Matic Jan used) ... and output it for currently selected shipping method.

Late in time but you may use:

add_action('woocommerce_product_options_general_product_data', 'my_custom_fields');

function my_custom_fields() {
    $field = array(
       //This ID will be use on the _postmeta table as key_name
       'id' => 'my_custom_message',
       //Text that goes inside the label tag
       'label' => 'Message:',
       //This text will appear on the description column
       'description' => 'This is a custom message not part of WooCommerce',
       //Boolean that determines the display of the description
       'desc_tip' => true,
       //Standard html input placeholder
       'placeholder' => 'Type a message',
    );
    woocommerce_wp_text_input($field);
}

add_action('woocommerce_process_product_meta', 'save_my_custom_fields');

function save_my_custom_fields($post_id) {
    update_post_meta(
        $post_id,
        'my_custom_message',
        esc_attr($POST['my_custom_message'])
    );
}

$field array in my opinion must have at minimum:

$field = array(
    'id' => 'my_custom_message',//This ID will be use on the _postmeta table as key_name
    'label' => 'Message:',//Text that goes inside the label tag
    'description' => 'This is a custom message not part of WooCommerce',//This text will appear on the description column
    'desc_tip' => true,//Boolean that determines the display of the description
    'placeholder' => 'Type a message',//Standard html input placeholder
);

You may also specify the following:

    'class' => 'css-class',//Class attributte for the input tag
    'style' => 'background:red',//Style attribute for the input tag
    'wrapper_class' => 'css-class',//Class for the wrapper of the input tag, it is a paragraph
Related