Home › Forums › Backend Issues (wp-admin) › Add ACF fields as Custom Order Line Item Meta › Reply To: Add ACF fields as Custom Order Line Item Meta
Hi there,
You’re right, my first reply is for front-end orders only.
Could you try the code below.
Let me know if it helps (i could re-use it someday).
Cheers,
Rémi
First, we write a small helper function to get and reorder your acf fields
<?php
//Helper function - Reorder acf datas
function maybe_reorder_acf_fields($order_id) {
$name = get_field('{slug/key}', $order_id) ? get_field('{slug/key}', $order_id) : null; //CHANGE with your own acf slug/key
$start_date = get_field('{slug/key}', $order_id) ? get_field('{slug/key}', $order_id) : null; //CHANGE with your own acf slug/key
$adults = get_field('{slug/key}', $order_id) ? get_field('{slug/key}', $order_id) : null; //CHANGE with your own acf slug/key
$children = get_field('{slug/key}', $order_id) ? get_field('{slug/key}', $order_id) : null; //CHANGE with your own acf slug/key
//Don't remember how datas are validated from get_field() - maybe esc/filter_var functions are useless
$custom_acf_metas = array(
'_acf_tour_customer_name' => esc_html($name),
'_acf_tour_start_date' => esc_html($start_date),
'_acf_tour_adults_nbr' => filter_var($adults, FILTER_SANITIZE_NUMBER_INT),
'_acf_tour_child_nbr' => filter_var($children, FILTER_SANITIZE_NUMBER_INT)
);
return $custom_acf_metas;
}
Next we use WP save_post hook to add OR overwrite custom metas each time an order is saved in backend.
https://developer.wordpress.org/reference/hooks/save_post/
Note : my_save_custom_order_metas() will add your acf datas to all products in an order.
You may adapt this code and probably your acf datas depending on your needs.
<?php
//Add new metas to order item(s)
add_action( 'save_post', 'my_save_custom_order_metas', 10, 3 );
function my_save_custom_order_metas( $order_id, $order, $update ) {
//Not sure if post revisions are used for shop orders - it returns false on a valid $order_id
if ( !is_admin() || get_post_type( $order_id ) !== 'shop_order' || wp_is_post_revision( $order_id ) ) return;
//Uncomment those two lines if you want to target specific order status
// $order_status = $order->get_status();
// if( $order_status !== 'wc-processing' ) return null;
$custom_acf_metas = maybe_reorder_acf_fields($order_id);
//Loop over every items added to your order
if( $order->get_items() ) {
foreach ( $order->get_items() as $item_id => $item ) {
//Nested loop over reordered ACF datas
foreach($custom_acf_metas as $new_meta_key => $new_meta_value) {
//Uncomment the two lines below if you don't want to overwrite your values
//$new_meta_exists = wc_get_order_item_meta( $item_id, $new_meta_key, true);
// if( $new_meta_exists !== false ) continue;
if( $new_meta_value !== null ) {
//Probably not really needed too - could be useful
$new_meta_key = sanitize_key($new_meta_key);
$new_meta_value = sanitize_meta( $new_meta_key, $new_meta_value, 'order_itemmeta' );
//Add new meta
$item->add_meta_data(
$new_meta_key,
$new_meta_value,
true
);
}
}
//Don't forget to save modified order here
$order->save();
}
}
}
Finally we keep our last 2 woocommerce filters to modify back-end display key + email and customer account item details (human readable for both).
<?php
//Modify our custom meta key to make it human readable from back-end
add_filter('woocommerce_order_item_display_meta_key', 'filter_wc_order_item_display_meta_key', 20, 3 );
function filter_wc_order_item_display_meta_key( $display_key, $meta, $item ) {
//Don't know if there is a better way to retrieve $order_id (and related acf datas)
$item_datas = $item->get_data();
$order_id = $item_datas['order_id'];
$custom_acf_metas = maybe_reorder_acf_fields($order_id);
// Change displayed label for specific order item meta key
foreach($custom_acf_metas as $new_meta_key => $new_meta_value) {
switch($new_meta_key) {
case '_acf_tour_customer_name' :
$new_display_key = '[your_display_key]'; //CHANGE with your own value
break;
case '_acf_tour_start_date' :
$new_display_key = '[your_display_key]'; //CHANGE with your own value
break;
case '_acf_tour_adults_nbr' :
$new_display_key = '[your_display_key]'; //CHANGE with your own value
break;
case '_acf_tour_child_nbr' :
$new_display_key = '[your_display_key]'; //CHANGE with your own value
break;
}
//Not sure if is_admin is necessary
if( is_admin() && $item->get_type() === 'line_item' && $meta->key === $new_meta_key ) {
$display_key = __($new_display_key, "my-text-domain" );
}
}
return $display_key;
}
// Add custom cart item data to emails AND customer account order details
add_filter( 'woocommerce_order_item_name', 'my_custom_data_in_email', 10, 2 );
function my_custom_data_in_email( $product_name, $item ) {
$item_datas = $item->get_data();
$order_id = $item_datas['order_id'];
$custom_acf_metas = maybe_reorder_acf_fields($order_id);
// Change displayed label for specific order item meta key
foreach($custom_acf_metas as $new_meta_key => $new_meta_value) {
switch($new_meta_key) {
case '_acf_tour_customer_name' :
$new_display_key = '[your_display_key]'; //CHANGE with your own value
break;
case '_acf_tour_start_date' :
$new_display_key = '[your_display_key]'; //CHANGE with your own value
break;
case '_acf_tour_adults_nbr' :
$new_display_key = '[your_display_key]'; //CHANGE with your own value
break;
case '_acf_tour_child_nbr' :
$new_display_key = '[your_display_key]'; //CHANGE with your own value
break;
}
if( isset( $item[$new_meta_key] ) ) {
$product_name .= sprintf(
'<ul><li>%s: %s</li></ul>',
__( $new_display_key, 'RemSEO' ),
esc_html( $item[$new_meta_key] )
);
}
}
return $product_name;
}
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Privacy Policy. If you continue to use this site, you consent to our use of cookies.