Add custom fields as cart item meta and order item meta in WooCommerce
Update (related to comments):
- Limit the functionality to only one product ID
- Add all checkboxes values as a coma separated string
To get easily the label names of your checkboxes as values and to "refactor to help include more checkboxes options would be helpful to reduce written code" I have added a simple function where you will set the key/value pairs for each checkbox you want to display and process…
So I have revisited all your code:
// HERE set the array of pairs keys/values for your checkboxes
function custom_checkboxes(){
return array(
'mm_chicken_cutlet_bento' => __( "Chicken Cutlet Bento", "aoim"),
'mm_roasted_pork_rib_bento' => __( "Roasted Pork Rib Bento", "aoim"),
);
}
// Displaying the checkboxes
add_action( 'woocommerce_before_add_to_cart_button', 'add_fields_before_add_to_cart' );
function add_fields_before_add_to_cart( ) {
global $product;
if( $product->get_id() != 2 ) return; // Only for product ID "2"
?>
<div class="simple-selects">
<div class="col-md-6">
<h3><?php _e("Main meals", "aoim"); ?></h3>
<?php foreach( custom_checkboxes() as $key => $value ): ?>
<p><input type="checkbox" name="<?php echo $key; ?>" id="<?php echo $key; ?>"><?php echo ' ' . $value; ?></p>
<?php endforeach; ?>
</div>
</div>
<?php
}
// Add data to cart item
add_filter( 'woocommerce_add_cart_item_data', 'add_cart_item_data', 25, 2 );
function add_cart_item_data( $cart_item_data, $product_id ) {
if( $product_id != 2 ) return $cart_item_data; // Only for product ID "2"
// Set the data for the cart item in cart object
$data = array() ;
foreach( custom_checkboxes() as $key => $value ){
if( isset( $_POST[$key] ) )
$cart_item_data['custom_data'][$key] = $data[$key] = $value;
}
// Add the data to session and generate a unique ID
if( count($data > 0 ) ){
$cart_item_data['custom_data']['unique_key'] = md5( microtime().rand() );
WC()->session->set( 'custom_data', $data );
}
return $cart_item_data;
}
// Display custom data on cart and checkout page.
add_filter( 'woocommerce_get_item_data', 'get_item_data' , 25, 2 );
function get_item_data ( $cart_data, $cart_item ) {
if( $cart_item['product_id'] != 2 ) return $cart_data; // Only for product ID "2"
if( ! empty( $cart_item['custom_data'] ) ){
$values = array();
foreach( $cart_item['custom_data'] as $key => $value )
if( $key != 'unique_key' ){
$values[] = $value;
}
$values = implode( ', ', $values );
$cart_data[] = array(
'name' => __( "Option", "aoim"),
'display' => $values
);
}
return $cart_data;
}
// Add order item meta.
add_action( 'woocommerce_add_order_item_meta', 'add_order_item_meta' , 10, 3 );
function add_order_item_meta ( $item_id, $cart_item, $cart_item_key ) {
if ( isset( $cart_item[ 'custom_data' ] ) ) {
$values = array();
foreach( $cart_item[ 'custom_data' ] as $key => $value )
if( $key != 'unique_key' ){
$values[] = $value;
}
$values = implode( ', ', $values );
wc_add_order_item_meta( $item_id, __( "Option", "aoim"), $values );
}
}
This code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works.
You will get something like this:
I have added "Option", as label to avoid the value repetition…
Comments
-
omukiguy almost 2 years
This is a plugin on how to add add cart item meta & order item meta for my WooCommerce order. Initially my code below worked well for input type=text. It returns the label for value and the inputed value.
On conversion to
type=checkbox
the code returnslabel
andvalue="on"
for those that are checked.I would like to return the only value names of checked values (ignore the values unchecked).
A refactor to help include more checkboxes options would be helpful to reduce written code.
My code:
<?php global $woocommerce, $product, $post; add_action( 'woocommerce_before_add_to_cart_button', 'add_fields_before_add_to_cart' ); function add_fields_before_add_to_cart( ) { ?> <div class="simple-selects"> <div class="col-md-6"> <h3>Main meals</h3> <p><input type="checkbox" name="mm_chicken_cutlet_bento" id="mm_chicken_cutlet_bento"><?php _e( "Chicken Cutlet Bento", "aoim"); ?></p> <p><input type="checkbox" name="mm_roasted_pork_rib_bento" id="mm_roasted_pork_rib_bento"><?php _e( "Roasted Pork Rib Bento", "aoim"); ?></p> </div> </div> <?php } /** * Add data to cart item */ add_filter( 'woocommerce_add_cart_item_data', 'add_cart_item_data', 25, 2 ); function add_cart_item_data( $cart_item_meta, $product_id ) { if ( isset( $_POST ['mm_chicken_cutlet_bento'] ) && isset( $_POST ['mm_roasted_pork_rib_bento'] ) ) { $custom_data = array() ; $custom_data [ 'mm_chicken_cutlet_bento' ] = isset( $_POST ['mm_chicken_cutlet_bento'] ) ? sanitize_text_field ( $_POST ['mm_chicken_cutlet_bento'] ) : "" ; $custom_data [ 'mm_roasted_pork_rib_bento' ] = isset( $_POST ['mm_roasted_pork_rib_bento'] ) ? sanitize_text_field ( $_POST ['mm_roasted_pork_rib_bento'] ): "" ; $cart_item_meta ['custom_data'] = $custom_data ; } return $cart_item_meta; } /** * Display custom data on cart and checkout page. */ add_filter( 'woocommerce_get_item_data', 'get_item_data' , 25, 2 ); function get_item_data ( $other_data, $cart_item ) { if ( isset( $cart_item [ 'custom_data' ] ) ) { $custom_data = $cart_item [ 'custom_data' ]; $other_data[] = array( 'name' => 'Chicken Cutlet Bento', 'display' => $custom_data['mm_chicken_cutlet_bento'] ); $other_data[] = array( 'name' => 'Roasted Pork Rib Bento', 'display' => $custom_data['mm_roasted_pork_rib_bento'] ); } return $other_data; } /** * Add order item meta. */ add_action( 'woocommerce_add_order_item_meta', 'add_order_item_meta' , 10, 2); function add_order_item_meta ( $item_id, $values ) { if ( isset( $values [ 'custom_data' ] ) ) { $custom_data = $values [ 'custom_data' ]; wc_add_order_item_meta( $item_id, 'Chicken Cutlet Bento', $custom_data['mm_chicken_cutlet_bento'] ); wc_add_order_item_meta( $item_id, 'Roasted Pork Rib Bento', $custom_data['mm_roasted_pork_rib_bento'] ); } } ?>
-
omukiguy over 6 yearsThe refactor works well. There a few tweeks to add. 1. Can this be restricted to one(only) product say to a product with a particular ID? 2. I have updated my question with image to show that I meant by "I would like to return the only value names of checked values (ignore the values unchecked)." I need to display these in the order table on checkout when they are just comma separated.
-
omukiguy over 6 yearse.g if Chicken Cutlet Bento and Roasted Pork Rib Bento are checked as options, they should be listed under the order table as "Chicken Cutlet Bento , Roasted Pork Rib Bento, example 3, example 4" I edited the question with an image to show what I mean.
-
LoicTheAztec over 6 years@omukiguy I have updated the code for your first request… to limit this for one product only.
-
omukiguy over 6 yearsI am still lost at your comment above. Maybe I am stuck in my workflow thought. Ideally we would just echo the "Chicken Cutlet Bento , Roasted Pork Rib Bento," with commas. No need to change the structure. I am bad with php arrays but we could restructure
add_filter( 'woocommerce_get_item_data', 'get_item_data' , 25, 2 );
function to that end -
LoicTheAztec over 6 years@omukiguy Ok let me try something…
-
omukiguy over 6 yearsThanks. i tried
global $product; if( $product->get_id() != 2 ) return; // Only for product ID "2"
I forgot to localize theglobal $product;
to function. -
LoicTheAztec over 6 years@omukiguy Ok updated and tested… It works as you expect now.