Add a custom text field to WooCommerce admin product data “Variations”

In wooCommerce admin product pages, on variable products you can have product variations. See below the “variations” settings section:

enter image description here

What Im trying to achieve:

I have already been able to add a text field for regular price and sales price for simple products on admin “product data” metabox under “General” section.
Now I need to add a new text field “Cost price” for variable products under “variations” section, but I had no idea how to add this.

So I started searching the scripts/reading WooCommerce documentation and I Managed to add the new text field by editing includes/admin/metabox/html-variation-admin.php, adding the code below to it:

woocommerce_wp_text_input(
    array(
        'id'            => "variable_cost_price{$loop}",
        'name'          => "variable_cost_price[{$loop}]",
        'value'         => wc_format_localized_price( $variation_object->get_cost_price( 'edit' ) ),
        'data_type'     => 'price',
        'label'         => $label ,
        'wrapper_class' => 'form-row form-row-last',
    )
);

I knew this was going to work as I cloned this from “Regular Price” form field.

My problem: Of course having the text field there is pointless if it does not save to the database and bring back the data to display on page load. Again I’m not 100% sure but I thought I had to make some more additions.

What I have tried: I have add the the method get_cost_price to the class-wc-ajax.php script as i saw one there already for get_regular_price. I also saw lines in class-wc-meta-box-product-data.php which referred to regular_price so I added an entry for my new cost_price, see below to what I added (I added the cost_price line):

$errors = $variation->set_props(
    array(
        'status'            => isset( $_POST['variable_enabled'][ $i ] ) ? 'publish' : 'private',
        'menu_order'        => wc_clean( $_POST['variation_menu_order'][ $i ] ),
        'regular_price'     => wc_clean( $_POST['variable_regular_price'][ $i ] ),
        'sale_price'        => wc_clean( $_POST['variable_sale_price'][ $i ] ),
        'cost_price'        => wc_clean( $_POST['variable_code_price'][ $i ] ),
        // .. more code here..

What have I missed, did I need to make a change in yet another script?

Again, the text field is displaying but entering data and clicking save changes doesn’t actually seem to be adding anything to the postmeta table.

EDIT: I do not need this displaying on the front end website, this is purely for backend data for me to store

2 Answers
2

Overriding core files is really something to avoid absolutely for many reasons.

To add a custom field to product variations options prices and save the value on save, use this:

// Admin: Add custom field in product variations options pricing
add_action( 'woocommerce_variation_options_pricing', 'add_variation_custom_option_pricing', 10, 3 );
function add_variation_custom_option_pricing( $loop, $variation_data, $variation ){

   woocommerce_wp_text_input( array(
        'id'            => '_cost_price['.$loop.']',
        'label'         => __("Cost Price", "woocommerce") . ' (' . get_woocommerce_currency_symbol() . ')',
        'class' => 'short wc_input_price',
        'data_type'     => 'price',
        'wrapper_class' => 'form-row form-row-first',
        'value'         => wc_format_localized_price( get_post_meta( $variation->ID, '_cost_price', true ) )
    ) );
}

// Admin: Save custom field value from product variations options pricing
add_action( 'woocommerce_save_product_variation', 'save_variation_custom_option_pricing', 10, 2 );
function save_variation_custom_option_pricing( $variation_id, $i ){
    if( isset($_POST['_cost_price'][$i]) ){
        update_post_meta( $variation_id, '_cost_price', wc_clean( wp_unslash( str_replace( ',', '.', $_POST['_cost_price'][$i]) ) ) );
    }
}

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

enter image description here


USAGE – If you need to use it to get the value:

1) From the variation ID

$cost_price = update_post_meta( $variation_id, '_cost_price', true );

2) From the product variation object

$cost_price = $variation->get_meta('_cost_price');

Leave a Comment