skip to Main Content

I can add a custom variable to a WooCommerce order, using code like this – but only if the code is on the product page:

<form action="<?php echo esc_url( wc_get_checkout_url() ); ?>" method="post">   
    <?php
  $value = isset( $_POST['dogname'] ) ? sanitize_text_field( $_POST['dogname'] ) : '';
    echo '<div><label>Name of Dog</label><p><input name="dogname" value="' . $value . '"></p></div>';
?>  <button type="submit">Checkout</button> 
    </form>

But how do I add the data to the order it if I am not on the product page? I redirect the page after add to cart to a custom page. On this custom page the cart is already populated with the product . But submitting this form on the custom page – goes to checkout but does not update or add the variable to the order. How would I update the order with my custom variable from my custom page?

Maybe I need some extra code for the button to update the order on click?

What code would I use for a button – that on click would post the form values to my order, and direct to another page?

2

Answers


  1. Chosen as BEST ANSWER

    To add some more functionality to LoicTheAztec answer using his thankyou_display_dog_data function. His included action shows the function on thank you after checkout form

    add_action( 'woocommerce_admin_order_data_after_shipping_address', 'thankyou_display_dog_data' );  //add  to admin order data under shipping
    add_action( 'woocommerce_admin_order_data_after_billing_address', 'thankyou_display_dog_data' );  //add  to admin under billing - pick one or duplicate of shipping
    add_action( 'woocommerce_order_details_after_order_table', 'thankyou_display_dog_data' );  //add to frontend customers my account  
    add_action( 'woocommerce_email_after_order_table', 'thankyou_display_dog_data', 15, 2 );  // add to emails
    

  2. Here below is a way to get posted data available in checkout page and anywhere else without loosing this posted data. For that we set the posted data to a WC session variable, so this posted data is available at any moment when needed.

    The form on your page (example with multiple fields):

    ?><form action="<?php echo esc_url( wc_get_checkout_url() ); ?>" method="post">
        <?php
        $dogname  = isset( $_POST['dogname'] ) ? sanitize_text_field( $_POST['dogname'] ) : '';
        $dogcolor = isset( $_POST['dogcolor'] ) ? sanitize_text_field( $_POST['dogcolor'] ) : '';
        ?>
        <div><label><?php _e("Name of Dog");  ?></label><p><input name="dogname"  value="<?php echo $dogname;  ?>"></p></div>
        <div><label><?php _e("Color of Dog"); ?></label><p><input name="dogcolor" value="<?php echo $dogcolor; ?>"></p></div>
        <button class="button" type="submit" name="dog_form" value="submited"><?php _e("Checkout"); ?></button>
    </form><?php
    

    The code that set the posted data to a WC_Session variable:

    // Early enable customer WC_Session
    add_action( 'init', 'wc_session_enabler' );
    function wc_session_enabler() {
        if ( is_user_logged_in() || is_admin() )
            return;
    
        if ( isset(WC()->session) && ! WC()->session->has_session() ) {
            WC()->session->set_customer_session_cookie( true );
        }
    }
    
    // Set posted data in a WC session variable
    add_action( 'template_redirect', 'set_custom_posted_data_to_wc_session' );
    function set_custom_posted_data_to_wc_session() {
        if ( is_checkout() && ! is_wc_endpoint_url() ) {
            if ( isset($_POST['dog_form']) ) {
                $values = array(); // Initializing
    
                if ( isset($_POST['dogname']) && ! empty($_POST['dogname']) ) {
                    $values['dogname'] = sanitize_text_field($_POST['dogname']);
                }
    
                if ( isset($_POST['dogcolor']) && ! empty($_POST['dogcolor']) ) {
                    $values['dogcolor'] = sanitize_text_field($_POST['dogcolor']);
                }
    
                // Set data to a WC_Session variable
                if ( ! empty($values) ) {
                    WC()->session->set('custom_data', $values);
                }
            }
        }
    }
    

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

    Then you can get that data on any function or template with:

    $values   = WC()->session->get('custom_data');
    $dogname  = isset($values['dogname']) ? $values['dogname'] : '';
    $dogcolor = isset($values['dogcolor']) ? $values['dogcolor'] : '';
    

    Save that data to order details:

    // Save WC session data as custom order meta data
    add_action( 'woocommerce_checkout_create_order', 'action_checkout_add_custom_order_meta', 10, 2 );
    function action_checkout_add_custom_order_meta( $order, $data ) {
        $values = WC()->session->get('custom_data'); // Get data from WC Session variable
    
        if( ! empty($values) ) {
            if ( isset($values['dogname']) ) {
                $order->update_meta_data( '_dogname', $values['dogname'] ); // Set dog name to order details
            }
            if ( isset($values['dogcolor']) ) {
                $order->update_meta_data( '_dogcolor', $values['dogcolor'] ); // Set dog color to order details
            }
            // Remove the WC_Session variable (as we don't need it anymore)
            WC()->session->__unset('custom_data');
        }
    }
    

    Code goes in functions.php file of the active child theme (or active theme).

    Then you can get that data from The WC_Order object order using:

    $order = wc_get_order( $order_id ); // If needed, get the WC_Order object from order Id
    
    $dogname  = $order->get_meta('_dogname');
    $dogcolor = $order->get_meta('_dogcolor');
    

    Like in this hooked function that will display data on "Order received" page:

    add_action( 'woocommerce_thankyou', 'thankyou_display_dog_data' ); 
    function thankyou_display_dog_data( $order_id ) { 
        
        $order = wc_get_order( $order_id ); // Get an instance of the WC_Order object
        
        $dog_name  = $order->get_meta('_dogname');
        $dog_color = $order->get_meta('_dogcolor');
         
        echo ! empty($dog_name) ? '<p>' . $dog_name .'<p>' : ''; 
        echo ! empty($dog_color) ? '<p>' . $dog_color .'<p>' : ''; 
    } 
    

    Tested and works on last WooCommerce version.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search