Search code examples
phpwordpresswoocommercecheckoutshipping-method

Add radio buttons to specific shipping method on WooCommerce checkout


I added a new shipping method "pickup from store" with free shipping to WooCommerce.

I have 2 stores, "Barsha" and "Deira". I would like when customer choose pickup from a store to be able to select which store he will visit.

Here is what I added to cart-shipping.php template file:

<?php                   
    <hr><p>Please choose the pickup store:</p>
        <input type="radio" id="barsha" sname="store" value="barsha">
        <label for="barsha">Barsha<a href=""> Check Location</a></label><br>
        <input type="radio" id="deira" sname="store" value="deira">
        <label for="deira">Deira<a href=""> Check Location</a></label>

    $sname= sname;
    if ( $sname = 'barsha'); {
        printf ('barsha')
    } else {
        printf ('deira')
    }
?>

But I can't get it working. How can I add some radio buttons to a specific shipping method and save the chosen option when order is submitted?

Solution

  • I suppose that in your case, you want to display some fields under "Local pickup" WooCommerce enabled shipping method.

    Instead of overriding cart-shipping.php template, you can better use the dedicated action hook for shipping methods that will allow you to display fields for a specific shipping method.

    The following code will allow you to display 2 radio buttons under "Local pickup" shipping method, when it's selected. If customer forget to choose a store, a message will remind him to chose a store for pickup. Then when order will be placed, the chosen store will be saved as custom order meta data, displayed in admin order under the billing address and everywhere near the chosen shipping method (orders and email notifications):

    // Add custom fields to a specific selected shipping method
    add_action( 'woocommerce_after_shipping_rate', 'pickup_store_custom_field', 100, 2 );
    function pickup_store_custom_field( $method, $index ) {
        // Only on checkout page and for Local pickup shipping method
        if( is_cart() || $method->method_id !== 'local_pickup' )
            return;
    
        $chosen_shipping_methods = WC()->session->get('chosen_shipping_methods')[ $index ];
    
        $chosen_method_id = explode(':', $chosen_shipping_methods);
        $chosen_method_id = reset($chosen_method_id);
    
        // Only when the chosen shipping method is "local_pickup"
        if( $chosen_method_id !== 'local_pickup' )
            return;
    
        echo '<div class="wrapper-pickup_store" style="margin-top:16px">
            <label class="title">' . __("Choose your pickup store") . ':</label><br>
            <label for="barsha-store">
                <input type="radio" id="barsha-store" name="pickup_store" value="Barsha">' 
                . __("Barsha") . '<a href="#"><small> '. __("Check Location") . '</small></a>
            </label><br>
            <label for="deira-store">
                <input type="radio" id="deira-store" name="pickup_store" value="Deira">' 
                . __("Deira") . '<a href="#"><small> '. __("Check Location") . '</small></a>
            </label>
        </div>';
    }
    
    // Pickup store field validation
    add_action('woocommerce_checkout_process', 'pickup_store_checkout_validation');
    function pickup_store_checkout_validation() {
    
        $chosen_shipping_methods = WC()->session->get('chosen_shipping_methods')['0'];
    
        $chosen_method_id = explode(':', $chosen_shipping_methods);
        $chosen_method_id = reset($chosen_method_id);
    
        if( $chosen_method_id === 'local_pickup' && empty( $_POST['pickup_store'] ) )
            wc_add_notice( __("Please choose a pickup store"), "error" );
    }
    
    // Save chosen Pickup store as custom order meta data
    add_action( 'woocommerce_checkout_create_order', 'pickup_store_update_order_meta' );
    function pickup_store_update_order_meta( $order ) {
        if( isset( $_POST['pickup_store'] ) && ! empty( $_POST['pickup_store'] ) )
            $order->update_meta_data( 'pickup_store', esc_attr( $_POST['pickup_store'] ) );
    }
    
    // Display the chosen pickup store under billing address
    add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_pickup_store_on_order_edit_pages' );
    function display_pickup_store_on_order_edit_pages( $order ){
        if( $pickup_store = $order->get_meta( 'pickup_store' ) )
            echo '<p><strong>Pickup store:</strong> '.$pickup_store.'</p>';
    }
    
    // Display the chosen pickup store below the chosen shipping method everywhere
    add_filter( 'woocommerce_get_order_item_totals', 'display_pickup_store_on_order_item_totals', 1000, 3 );
    function display_pickup_store_on_order_item_totals( $total_rows, $order, $tax_display ){
        if( $pickup_store = $order->get_meta( 'pickup_store' ) ) {
            $new_total_rows = [];
    
            // Loop through order total rows
            foreach( $total_rows as $key => $values ) {
                $new_total_rows[$key] = $values;
                // Inserting the pickup store under shipping method
                if( $key === 'shipping' ) {
                    $new_total_rows['pickup_store'] = array(
                        'label' => __("Pickup store"),
                        'value' => $pickup_store
                    );
                }
            }
            return $new_total_rows;
        }
    
        return $total_rows;
    }
    

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


    On checkout page:

    enter image description here

    On customer Orders (and email notifications):

    enter image description here

    On admin order edit pages (under the billing address):

    enter image description here


    Related answers: