Passing custom data from cart items to Order meta in Woocommerce 3

六月ゝ 毕业季﹏ 提交于 2019-12-22 00:18:00

问题


I have implemented a custom HTML Form and asking for some data which my customers will pass to place order successfully. Without these details my order has no importance.

For HTML form, I am referencing some custom PHP script which is below and which processes POST data from the Form and creates Cart with these data programmatically. Thanks @LoicTheAztec to help me achieve this.

The script.php file code:

<?php

    require_once("../wp-load.php");

    $customer_name = $_POST["customer_name"];
    $customer_email = $_POST["customer_email"];
    $customer_sex = $_POST["customer_sex"];
    $customer_age = $_POST["customer_age"];
    $product_id = $_POST["product_id"];

$custom_data = array(); // Initializing

    if( isset($_POST['customer_name']) && ! empty($_POST['customer_name']) )
        $custom_data['custom_data']['name']  =  $_POST['customer_name'];
    if( isset($_POST['customer_email']) && ! empty($_POST['customer_email']) )
        $custom_data['custom_data']['email'] = $_POST['customer_email'];
    if( isset($_POST['customer_sex']) && ! empty($_POST['customer_sex']) )
        $custom_data['custom_data']['sex']   = $_POST['customer_sex'];
    if( isset($_POST['customer_age']) && ! empty($_POST['customer_age']) )
        $custom_data['custom_data']['age']   = $_POST['customer_age'];

    global $woocommerce;

    if (WC()->cart->add_to_cart( $product_id, '1', '0', array(), $custom_data )) {
        var_dump($product_id);
    } else {
        var_dump($customer_name);
    }

    header("Location: ./checkout");
?>

As you see we have programmatically created a cart item using WC_Cart add_to_cart() method. So, all custom data is being saved to Cart as custom cart item data.

And now, we have also placed a code block into functions.php to print these data on Checkout page.

add_action( 'woocommerce_after_order_notes', 'my_custom_checkout_field' );

function my_custom_checkout_field( $checkout ) {

    //var_dump($checkout);
    global $woocommerce;

    echo '<div id="my_custom_checkout_field"><h2>' . __('Child Info') . '</h2>';

    foreach ( $woocommerce->cart->get_cart() as $cart_item ) {
        if( isset($cart_item['custom_data']) ) {

            $custom_data = $cart_item['custom_data'];

            echo("<div>Name: <strong>" . $custom_data['name'] . "</strong></div>");
            echo("<div>Email: <strong>" . $custom_data['email'] . "</strong></div>");
            echo("<div>Gender: <strong>" . $custom_data['sex'] . "</strong></div>");
            echo("<div>Age: <strong>" . $custom_data['age'] . "</strong></div>");

        }

    }

    echo '</div>';

}

Now, I am trying to add these data printed on Checkout page to the Order page as well. As my order can't be completed without these data, user need to fill up these data and when he creates order, these data needs to be passed to the Order Summary page as well. And admin also needs to be able to see these data so he can process the order.

I hope this description clears everything and thanks again @LoicTheAztec to make me able to do this. Thank you very much.


回答1:


Update 2 - Two steps

1) Saving data:

We will save this custom customer data as "Hidden" order "item" meta data and then as order meta data too as this is related to subscriptions with a unique order item:

// Utility function: array of custom customer key/label pairs
function custom_data_keys_labels(){
    return array(
        'name'  => __('Customer name'),     'email' => __('Customer email'),
        'sex'   => __('Customer gender'),   'age'   => __('Customer age'),
    );
}

// Add/save custom field value as custom HIDDEN order item meta data
add_action( 'woocommerce_checkout_create_order_line_item', 'custom_field_update_order_item_meta', 20, 4 );
function custom_field_update_order_item_meta( $item, $cart_item_key, $values, $order ) {
    if ( ! isset( $values['custom_data'] ) )
        return;

    $custom_data = $values['custom_data'];
    $meta_data   = array();
    $labels_keys = custom_data_keys_labels();

    foreach( $labels_keys as $key => $label ){
        if ( isset( $custom_data[$key] ) )
            $meta_data[$key] = $custom_data[$key];
    }

    if ( sizeof( $meta_data ) > 0 )
        $item->update_meta_data( __('_customer_data'), $meta_data );

    return $cart_item_data;
}

// Add/save custom fields values as custom order meta data
add_action( 'woocommerce_checkout_create_order', 'my_custom_checkout_field_update_order_meta', 20, 2 );
function my_custom_checkout_field_update_order_meta( $order, $data ) {

    $order_items = $order->get_items(); // Order itesm
    $item        = reset($order_items); // Keep only the first order item

    $item_data   = $item->get_meta( '_customer_data' ); // Get custom customer data

    if( is_array($item_data) && sizeof($item_data) > 0 ){
        foreach( $item_data as $key => $value ) {
            if ( isset( $item_data[$key] ) )
                $order->update_meta_data( '_customer_' . $key, $value );
        }
        // Mark as data saved
        $order->update_meta_data( '_customer_data_set', true );
    }
}

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


2) Displaying saved custom data:

The code below also use our utility function custom_data_keys_labels()

// Order pages (frontend and admin) display
add_filter( 'woocommerce_order_details_after_order_table' , 'display_admin_order_meta_cutom_data', 20, 1 ); // Front
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_admin_order_meta_cutom_data', 20, 1 ); // Admin
function display_admin_order_meta_cutom_data( $order ){
    $labels_keys = custom_data_keys_labels();
    if( $order->get_meta( '_customer_data_set' ) ){
        if( is_admin() ){ // Admin
            echo '<p>';
            foreach( $labels_keys as $key => $label ){
                if ( $order->get_meta( '_customer_' . $key ) )
                    echo '<strong>' . $label . ':</strong> ' . $order->get_meta( '_customer_' . $key ) . '<br>';
            }
            echo '</p>';
        }
        else { // Front end: order view and Order received (thankyou)
            echo '<table class="woocommerce-table"><tbody>';
            foreach( $labels_keys as $key => $label ){
                if ( $order->get_meta( '_customer_' . $key ) )
                    echo '<tr><th>' . $label . ':</th><td>' . $order->get_meta( '_customer_' . $key ) . '</td></tr>';
            }
            echo '</tbody></table>';
        }
    }
}

// Email notifications display
add_filter( 'woocommerce_email_order_meta_fields' , 'display_email_cutom_data', 20, 3 );
function display_email_cutom_data ( $fields, $sent_to_admin, $order ) {
    $labels_keys = custom_data_keys_labels();
    if( $order->get_meta( '_customer_data_set' ) ){
        foreach( $labels_keys as $key => $label ){
            $fields['customer_' . $key] = array(
                'label' => $label,
                'value' => $order->get_meta( '_customer_' . $key ),
            );
        }
    }
    return $fields;
}

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




来源:https://stackoverflow.com/questions/51712831/passing-custom-data-from-cart-items-to-order-meta-in-woocommerce-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!