将订阅产品变体中的自定义元数据保存到订单

Save custom metadata from subscription product variation to order

我需要能够将管理数据添加到订阅产品变体(Woo 订阅扩展),以便在下订单时将此数据传递给履行中心。

我遇到的问题是从产品中获取这些值并将它们传递到订单和电子邮件通知中,以便它们可以正确导出、添加到运输标签并通过各种 woo 通知通过电子邮件发送。

我在订阅产品的变体中添加了自定义元字段。我可以向其中添加数据,它们会根据正确的变体 ID 将数据正确保存到数据库中。没问题。

我可以在购物车和结帐页面上显示自定义测试数据,并将这些数据保存到订单中,您将在代码中看到。

为简洁起见,代码简化如下,但实际上有 6 个文本字段:

// Add custom field inputs to each product variation
add_action( 'woocommerce_variation_options_pricing', 'add_custom_field_to_variations', 10, 3 );

function add_custom_field_to_variations( $loop, $variation_data, $variation ) {
    woocommerce_wp_text_input( 
        array(
            'id' => '_dose_customer_field[' . $loop . ']',
            'label'       => __( 'Dose (Customer)', 'woocommerce' ), 
            'placeholder' => __('Enter the treatment dosage','woocommerce' ),
            'desc_tip'    => 'true',
            'description' => __( 'Enter dosage info for this variation', 'woocommerce' ),
            'class' => '',
            'value' => get_post_meta( $variation->ID, '_dose_customer_field', true )
        )
    );
}

// Save custom field on product variation save 
add_action( 'woocommerce_save_product_variation', 'save_custom_field_variations', 10, 2 );

function save_custom_field_variations( $variation_id, $i ) {
    $_dose_customer_field = $_POST['_dose_customer_field'][$i];
    if ( isset( $_dose_customer_field ) ) update_post_meta( $variation_id, '_dose_customer_field', esc_attr( $_dose_customer_field ) );   
}

// Add metadata to cart item post.
add_filter( 'woocommerce_add_cart_item_data', 'add_custom_fields_cart_item_data', 10, 2 );

function add_custom_fields_cart_item_data( $cart_item_data, $product_id ){    

    $cart_item_data['custom_data']['_dose_customer_field'] = 'TEST DATA' /* HOW TO GET DATA FROM CUSTOM FIELD HERE */       

    $cart_item_data['custom_data']['unique_key'] = md5( microtime().rand() );
    WC()->session->set( 'custom_data', $cart_item_data['custom_data'] );

    return $cart_item_data;
}

// Display custom meta data on cart and checkout page.
add_filter( 'woocommerce_get_item_data', 'display_custom_fields_cart_item_data', 10, 2 );

function display_custom_fields_cart_item_data($item_data, $cart_item){

    if( ! array_key_exists( 'custom_data', $cart_item ) )
        return $item_data;

    if( array_key_exists( '_dose_customer_field', $cart_item['custom_data'] ) )
        $item_data[] = array(
            'key'   => __('Dose (Customer)', 'woocommerce'),
            'value' => $cart_item['custom_data']['_dose_customer_field']
        );

    return $item_data;
}

// Add metadata to the order.
add_action('woocommerce_checkout_create_order_line_item', 'save_custom_fields_as_order_item_meta', 20, 4);

function save_custom_fields_as_order_item_meta($item, $cart_item_key, $values, $order) {
    if( ! isset($values['custom_data']) )
        return;

    $text_domain ='woocommerce';

    if( array_key_exists('_dose_customer_field', $values['custom_data']) ){
        $item->update_meta_data( __('Dose (Customer)', $text_domain), $values['custom_data']['_dose_customer_field'] );
    }    
}

// Frontend & emails: Display data on notifications
add_action( 'woocommerce_order_item_meta_start', 'vp_order_item_display_commodity_code', 10, 4 );
function vp_order_item_display_commodity_code( $item_id, $item, $order, $plain_text ) {
    // Not on admin
    //if( is_admin() ) return;

    if( $value = $item->get_meta('_dose_customer_field') ) {
        $value = '<strong>' . __("Dose (Customer)", "woocommerce") . ':</strong> ' . esc_attr( $value );

        // On orders
        if( is_wc_endpoint_url() )
            echo '<div class="vp-ccode"><small>' . $value . '</small></div>';
        // On Emails
        else
            echo '<div>' . $value . '</div>';
    }
}

除了从自定义字段中获取数据外,一切正常。奇怪的是我必须创建一个新数组(这里称为 'custom_data')并将其添加到 cart_item_data,而产品变体的数据已经可用,尽管是私有的。

我的问题是如何获取 add_custom_fields_cart_item_data() 中的元数据?这甚至是正确的方法吗?

非常感谢

由于产品存在此自定义数据,您可以轻松获取并将其保存为订单项自定义数据(因此它会随处显示):

完整代码(修改了最后两个函数):

// Add custom field inputs to each product variation
add_action( 'woocommerce_variation_options_pricing', 'add_custom_field_to_variations', 10, 3 );
function add_custom_field_to_variations( $loop, $variation_data, $variation ) {
    woocommerce_wp_text_input( 
        array(
            'id' => '_dose_customer_field[' . $loop . ']',
            'label'       => __( 'Dose (Customer)', 'woocommerce' ), 
            'placeholder' => __('Enter the treatment dosage','woocommerce' ),
            'desc_tip'    => 'true',
            'description' => __( 'Enter dosage info for this variation', 'woocommerce' ),
            'class' => '',
            'value' => get_post_meta( $variation->ID, '_dose_customer_field', true )
        )
    );
}

// Save custom field on product variation save 
add_action( 'woocommerce_save_product_variation', 'save_custom_field_variations', 10, 2 );
function save_custom_field_variations( $variation_id, $i ) {
    $_dose_customer_field = $_POST['_dose_customer_field'][$i];
    if ( isset( $_dose_customer_field ) ) update_post_meta( $variation_id, '_dose_customer_field', esc_attr( $_dose_customer_field ) );   
}

// Display custom meta data on cart and checkout page.
add_filter( 'woocommerce_get_item_data', 'display_custom_fields_cart_item_data', 10, 2 );
function display_custom_fields_cart_item_data( $item_data, $cart_item ) {
    if( $value = $cart_item['data']->get_meta( '_dose_customer_field' ) )
        $item_data[] = array(
            'key'   => __('Dose (Customer)', 'woocommerce'),
            'value' => $value
        );

    return $item_data;
}

// Add metadata to the order item (and display it everywhere).
add_action('woocommerce_checkout_create_order_line_item', 'save_custom_fields_as_order_item_meta', 10, 4);
function save_custom_fields_as_order_item_meta( $item, $cart_item_key, $values, $order ) {
    if( $meta_value = $values['data']->get_meta( '_dose_customer_field' ) )
        $item->update_meta_data( __('Dose (Customer)', 'woocommerce'), $meta_value );  
}

代码进入您的活动子主题(或活动主题)的 functions.php 文件。应该可以。