17

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

dbc
  • 104,963
  • 20
  • 228
  • 340
Raunak Gupta
  • 10,412
  • 3
  • 58
  • 97
  • The table that you see is mix of HTML in `th` and `tfoot` while the data is populated using Mustache inspired Underscore.js templates. You can look at `\includes\admin\settings\views\html-admin-page-shipping-zone-methods.php` for more details. – Dhaval Shah Dec 12 '17 at 12:44
  • The model for Shipping Method settings is also based on Underscore.js template. So to modify the view and processing the entered data you have to use custom JS. For storing/retrieving the data part you can do so using core settings api and save them in options. For displaying the same on frontend you have to use hooks in each WC template. – Dhaval Shah Dec 12 '17 at 12:54

5 Answers5

4
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

Matic Jan
  • 103
  • 6
  • 2
    Ho would you do to get this data later on? For example I need it inside the action hook "woocommerce_after_shipping_rate" to show it after each label. – Ramon Carceles Sep 01 '20 at 19:52
2

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; 
    } 
Simas Joneliunas
  • 2,890
  • 20
  • 28
  • 35
Wprog_dy
  • 67
  • 5
2

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.

Marek
  • 588
  • 5
  • 12
0

If you use Matic Jan method and don't need all settings as Marek shown: use get_meta_data() on WC_Shipping_Rate object.

$shipping_rate->get_meta_data();
-1

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
  • 4
    he is trying to add fields to the shipping methods in the settings->shipping-zones->shipping-methods. Not on the product itself. – Jeremy Jun 29 '19 at 03:35