Search code examples
phpwordpresswoocommercemetadataorders

Save custom metadata to Woocommerce orders


In WooCommerce i've added 2 fields to a product with Toolset Types. So when you add a product you can set the expected delivery time in days or weeks.

On the cart and review page i've wrote some code to display the longest delivery time in the totals table.

Front-end layout

i've done this with the following code added before the closing table tag in cart-totals.php and review-order.php (ofcourse i've added this to my child theme).

     foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
                $product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );

                $amount_of_days = 0;

                $delivery_amount = get_post_meta($product_id, 'wpcf-aantal', true);
                $delivery_week_or_days = get_post_meta($product_id, 'wpcf-dagen-of-weken', true);

                if($delivery_week_or_days == "weken"){
                    $amount_of_days = $delivery_amount * 7;
                } else {
                    $amount_of_days = $delivery_amount;
                }
                $array_of_days[] = $amount_of_days;
    }

    $most_days = max($array_of_days);

    if ($most_days % 7 == 0){
        $most_time_string = $most_days/7 . ' weken';
    } else {
        $most_time_string = $most_days . ' dagen';
    }

    if (!empty($most_days)){

        echo '<tr class="custom-cart-delivery-time">';
            echo '<th>Geschatte levertijd</th>';
            echo '<td>' . $most_time_string. '</td>';
        echo '</tr>';
    }

My question is how do i actually safe this to an order? I want the estimated shipping time (as example: "3 weeks" or "2 days") to show in the order and invoice.


Solution

  • You could try to use the following (commented):

    // Utility function to get the "most day" value from cart object (cart items)
    function get_the_most_day(){
        $array_of_days = []; // Initializing;
    
        // Loop through cart items
        foreach ( WC()->cart->get_cart() as $cart_item ) {
            $delivery_amount       = get_post_meta($cart_item['product_id'], 'wpcf-aantal', true);
            $delivery_week_or_days = get_post_meta($cart_item['product_id'], 'wpcf-dagen-of-weken', true);
            $amount_of_days        = 0;
    
            $array_of_days[] = $delivery_week_or_days == "weken" ? $delivery_amount * 7 : $delivery_amount;
        }
        $most_days = max($array_of_days);
    
        return $most_days % 7 == 0 ? $most_days / 7 . ' weken' : $most_days . ' dagen'; 
    }
    
    // Save the most day in Woocommerce session (on checkout page)
    add_action( 'template_redirect', 'save_most_days_in_wc_session' );
    function save_most_days_in_wc_session() {
        // Only checkout page
        if( is_checkout() && ! is_wc_endpoint_url() ){
            WC()->session->set( 'most_day', get_the_most_day() );
        }
    }
    
    // Save the most day as custom meta data in the order
    add_action('woocommerce_checkout_create_order', 'save_the_most_day_as_order_meta_data', 20, 2);
    function save_the_most_day_as_order_meta_data( $order, $data ) {
        if( $most_day = WC()->session->get( 'most_day' ) ){
            $order->update_meta_data( '_most_day', $most_day );
        }
    }
    

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


    To get this "most day" value (2 ways):

    1) From the WC_Order $order variable Object

    $most_day_value = get_meta( '_most_day' );
    

    2) From the dynamic Order ID variable

    $most_day_value = get_post_meta( $order_id, '_most_day', true );