Based on Enhanced WooCommerce Custom Fields for Variations answer code for adding a custom field to a product variation which works.
I have added additional custom fields, 6 at all. When I update the product, the data does not save and does not display on the front end either.
What have I done incorrectly when adding the additional custom fields?
My code:
// Add a custom field to variation settings
add_action( 'woocommerce_product_after_variable_attributes', 'variation_settings_fields', 10, 3 );
function variation_settings_fields( $loop, $variation_data, $variation ) {
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_model[' . $variation->ID . ']',
'label' => __( 'model', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => 'true',
'description' => __( 'Enter the custom value here.', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_model', true )
)
);
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_wattage[' . $variation->ID . ']',
'label' => __( 'wattage', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => 'true',
'description' => __( 'Enter the custom value here.', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_wattage', true )
)
);
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_lumen[' . $variation->ID . ']',
'label' => __( 'lumen', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => 'true',
'description' => __( 'Enter the custom value here.', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_lumen', true )
)
);
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_material[' . $variation->ID . ']',
'label' => __( 'material', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => 'true',
'description' => __( 'Enter the custom value here.', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_material', true )
)
);
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_dimension[' . $variation->ID . ']',
'label' => __( 'dimension', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => 'true',
'description' => __( 'Enter the custom value here.', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_dimension', true )
)
);
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_year[' . $variation->ID . ']',
'label' => __( 'year', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => 'true',
'description' => __( 'Enter the custom value here.', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_year', true )
)
);
}
// Save custom field value from variation settings
add_action( 'woocommerce_admin_process_variation_object', 'save_variation_settings_fields', 10, 2 );
function save_variation_settings_fields( $variation, $loop ) {
if( isset($_POST['_model'][$loop]) ) {
$variation->update_meta_data( '_model', sanitize_text_field($_POST['_model'][$loop]) );
}
if( isset($_POST['_wattage'][$loop]) ) {
$variation->update_meta_data( '_wattage', sanitize_text_field($_POST['_wattage'][$loop]) );
}
if( isset($_POST['_lumen'][$loop]) ) {
$variation->update_meta_data( '_lumen', sanitize_text_field($_POST['_lumen'][$loop]) );
}
if( isset($_POST['_material'][$loop]) ) {
$variation->update_meta_data( '_material', sanitize_text_field($_POST['_material'][$loop]) );
}
if( isset($_POST['_dimension'][$loop]) ) {
$variation->update_meta_data( '_dimension', sanitize_text_field($_POST['_dimension'][$loop]) );
}
if( isset($_POST['_year'][$loop]) ) {
$variation->update_meta_data( '_year', sanitize_text_field($_POST['_year'][$loop]) );
}
}
// Add variation custom field to single variable product form
add_filter( 'woocommerce_available_variation', 'add_variation_custom_field_to_variable_form', 10, 3 );
function add_variation_custom_field_to_variable_form( $variation_data, $product, $variation ) {
$variation_data['model'] = $variation->get_meta('_model');
$variation_data['wattage'] = $variation->get_meta('_wattage');
$variation_data['lumen'] = $variation->get_meta('_lumen');
$variation_data['material'] = $variation->get_meta('_material');
$variation_data['dimension'] = $variation->get_meta('_dimension');
$variation_data['year'] = $variation->get_meta('_year');
return $variation_data;
}
add_action( 'woocommerce_product_additional_information', 'add_html_container_to_display_selected_variation_custom_field' );
function add_html_container_to_display_selected_variation_custom_field( $product ){
echo '<div class="custom_variation-text-field"></div>';
}
// Display selected variation custom field value to product the tab
add_action( 'woocommerce_after_variations_form', 'display_selected_variation_custom_field_js' );
function display_selected_variation_custom_field_js(){
?>
<script type="text/javascript">
(function($){
$('form.cart').on('show_variation', function(event, data) {
$('.custom_variation-text-field').text(data.text_field);
}).on('hide_variation', function(event) {
$('.custom_variation-text-field').text('');
});
})(jQuery);
</script>
<?php
}
To make it save the data, I have made some changes in the 1st function (2nd one stay unchanged):
// Add a custom field to variation settings
add_action( 'woocommerce_product_after_variable_attributes', 'variation_settings_fields', 10, 3 );
function variation_settings_fields( $loop, $variation_data, $variation ) {
woocommerce_wp_text_input( array(
'id' => '_model[' . $loop . ']',
'label' => __( 'model', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => 'true',
'description' => __( 'This is the description text...', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_model', true )
) );
woocommerce_wp_text_input(
array(
'id' => '_wattage[' . $loop . ']',
'label' => __( 'wattage', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => 'true',
'description' => __( 'This is the description text...', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_wattage', true )
) );
woocommerce_wp_text_input( array(
'id' => '_lumen[' . $loop . ']',
'label' => __( 'lumen', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => 'true',
'description' => __( 'This is the description text...', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_lumen', true )
) );
woocommerce_wp_text_input( array(
'id' => '_material[' . $loop . ']',
'label' => __( 'material', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => 'true',
'description' => __( 'This is the description text...', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_material', true )
) );
woocommerce_wp_text_input( array(
'id' => '_dimension[' . $loop . ']',
'label' => __( 'dimension', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => 'true',
'description' => __( 'This is the description text...', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_dimension', true )
) );
woocommerce_wp_text_input( array(
'id' => '_year[' . $loop . ']',
'label' => __( 'year', 'woocommerce' ),
'placeholder' => 'http://',
'desc_tip' => 'true',
'description' => __( 'Enter the custom value here.', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_year', true )
) );
}
// Save custom field value from variation settings
add_action( 'woocommerce_admin_process_variation_object', 'save_variation_settings_fields', 10, 2 );
function save_variation_settings_fields( $variation, $loop ) {
if( isset($_POST['_model'][$loop]) ) {
$variation->update_meta_data( '_model', sanitize_text_field($_POST['_model'][$loop]) );
}
if( isset($_POST['_wattage'][$loop]) ) {
$variation->update_meta_data( '_wattage', sanitize_text_field($_POST['_wattage'][$loop]) );
}
if( isset($_POST['_lumen'][$loop]) ) {
$variation->update_meta_data( '_lumen', sanitize_text_field($_POST['_lumen'][$loop]) );
}
if( isset($_POST['_material'][$loop]) ) {
$variation->update_meta_data( '_material', sanitize_text_field($_POST['_material'][$loop]) );
}
if( isset($_POST['_dimension'][$loop]) ) {
$variation->update_meta_data( '_dimension', sanitize_text_field($_POST['_dimension'][$loop]) );
}
if( isset($_POST['_year'][$loop]) ) {
$variation->update_meta_data( '_year', sanitize_text_field($_POST['_year'][$loop]) );
}
}
It should better work to custom fields data to database and display the saved values in admin.
Now the frontend display part is wrong (your last 2 functions).
You need first to think about how you want to display that multiple custom fields, how should be the html structure and the labels related to each custom field. So edit your question as I can't guess that for you.
Here is a working example with all your custom fields, to display the data in frontend single product pages, for the selected variation:
// Add variation custom field to single variable product form
add_filter( 'woocommerce_available_variation', 'add_variation_custom_field_to_variable_form', 10, 3 );
function add_variation_custom_field_to_variable_form( $variation_data, $product, $variation ) {
$variation_data['model'] = $variation->get_meta('_model');
$variation_data['wattage'] = $variation->get_meta('_wattage');
$variation_data['lumen'] = $variation->get_meta('_lumen');
$variation_data['material'] = $variation->get_meta('_material');
$variation_data['dimension'] = $variation->get_meta('_dimension');
$variation_data['year'] = $variation->get_meta('_year');
return $variation_data;
}
add_action( 'woocommerce_product_additional_information', 'add_html_container_to_display_selected_variation_custom_field' );
function add_html_container_to_display_selected_variation_custom_field( $product ){
echo '<div class="custom_variation-text-field">aaa</div>';
}
// Display selected variation custom field value to product the tab
add_action( 'woocommerce_after_variations_form', 'display_selected_variation_custom_field_js' );
function display_selected_variation_custom_field_js(){
?>
<script type="text/javascript">
(function($){
var a = '.custom_variation-text-field', b = $(a).html();
$('form.cart').on('show_variation', function(event, data) {
outputHtml = '';
if( data.model ) {
outputHtml += '<span><strong><?php _e("Model"); ?><strong>: '+data.model+'<span><br>';
}
if( data.wattage ) {
outputHtml += '<span><strong><?php _e("Wattage"); ?><strong>: '+data.wattage+'<span><br>';
}
if( data.lumen ) {
outputHtml += '<span><strong><?php _e("Lumen"); ?><strong>: '+data.lumen+'<span><br>';
}
if( data.material ) {
outputHtml += '<span><strong><?php _e("Material"); ?><strong>: '+data.material+'<span><br>';
}
if( data.dimension ) {
outputHtml += '<span><strong><?php _e("Dimension"); ?><strong>: '+data.dimension+'<span><br>';
}
if( data.year ) {
outputHtml += '<span><strong><?php _e("Year"); ?><strong>: '+data.year+'<span>';
}
if( outputHtml ) {
$(a).html(outputHtml);
}
}).on('hide_variation', function(event) {
$(a).html(b);
});
})(jQuery);
</script>
<?php
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Related
I'm trying to filter the products in the shop page by stock. Below is the code I added in my child theme's functions.php to add 2 new stock statuses. Which is working fine as expected.
function add_custom_stock_type() {
?>
<script type="text/javascript">
jQuery(function(){
jQuery('._stock_status_field').not('.custom-stock-status').remove();
});
</script>
<?php
woocommerce_wp_select( array( 'id' => '_stock_status', 'wrapper_class' => 'custom-stock-status', 'label' => __( 'Stock status', 'woocommerce' ), 'options' => array(
'readytoship' => __( 'Ready to ship', 'woocommerce' ),
'outofstock' => __( 'Out of stock', 'woocommerce' ),
'onbackorder' => __( 'Backorder', 'woocommerce' ),
'customized' => __( 'Customized', 'woocommerce' ),
), 'desc_tip' => true, 'description' => __( 'Controls whether or not the product is listed as "in stock" or "out of stock" on the frontend.', 'woocommerce' ) ) );
}
add_action('woocommerce_product_options_stock_status', 'add_custom_stock_type');
function save_custom_stock_status( $product_id ) {
update_post_meta( $product_id, '_stock_status', wc_clean( $_POST['_stock_status'] ) );
}
add_action('woocommerce_process_product_meta', 'save_custom_stock_status',99,1);
function woo_add_custom_general_fields_save_two( $post_id ){
// Select
$woocommerce_select = $_POST['_stock_status'];
if( !empty( $woocommerce_select ) )
update_post_meta( $post_id, '_stock_status', esc_attr( $woocommerce_select ) );
else
update_post_meta( $post_id, '_stock_status', '' );
}
function woocommerce_get_custom_availability( $data, $product ) {
switch( $product->stock_status ) {
case 'readytoship':
$data = array( 'availability' => __( 'Ready to ship', 'woocommerce' ), 'class' => 'ready-to-ship' );
break;
case 'outofstock':
$data = array( 'availability' => __( 'Out of stock', 'woocommerce' ), 'class' => 'out-of-stock' );
break;
case 'onbackorder':
$data = array( 'availability' => __( 'Backorder', 'woocommerce' ), 'class' => 'onbackorder' );
break;
case 'customized':
$data = array( 'availability' => __( 'Customized', 'woocommerce' ), 'class' => 'customized' ); //added new one
break;
}
return $data;
}
add_action('woocommerce_get_availability', 'woocommerce_get_custom_availability', 10, 2);
So this is the code I'm using and I'm getting the stock status dropdown perfectly: https://prnt.sc/vrm5a9
I'm trying to "Filter Products Based on Stock Type" which I'm quite unsure how. I planned to place it in the woocommerce sidebar along with other filters like categories, price slider and stuff.
Any help is appreciated.
I'm trying to create custom fields for variable products.
So far I have used the code from this github: https://gist.github.com/maddisondesigns/e7ee7eef7588bbba2f6d024a11e8875a
I have changed the code to my needs and currently have this in my functions.php:
/*
* Add our Custom Fields to variable products
*/
function mytheme_woo_add_custom_variation_fields( $loop, $variation_data, $variation ) {
echo '<div class="options_group form-row form-row-full">';
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_variable_article_number[' . $variation->ID . ']',
'label' => __( 'Article number', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => true,
'description' => __( 'Article number', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_variable_article_number', true ),
)
);
woocommerce_wp_text_input(
array(
'id' => '_variable_ean_code[' . $variation->ID . ']',
'label' => __( 'EAN code', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => true,
'description' => __( 'EAN code', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_variable_ean_code', true ),
)
);
woocommerce_wp_text_input(
array(
'id' => '_variable_shelf_life[' . $variation->ID . ']',
'label' => __( 'Shelf life', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => true,
'description' => __( 'Shelf life', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_variable_shelf_life', true ),
)
);
echo '</div>';
}
// Variations tab
// add_action( 'woocommerce_variation_options', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After variation Enabled/Downloadable/Virtual/Manage Stock checkboxes
// add_action( 'woocommerce_variation_options_pricing', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Price fields
// add_action( 'woocommerce_variation_options_inventory', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Manage Stock fields
// add_action( 'woocommerce_variation_options_dimensions', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Weight/Dimension fields
// add_action( 'woocommerce_variation_options_tax', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Shipping/Tax Class fields
// add_action( 'woocommerce_variation_options_download', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After Download fields
add_action( 'woocommerce_product_after_variable_attributes', 'mytheme_woo_add_custom_variation_fields', 10, 3 ); // After all Variation fields
/*
* Save our variable product fields
*/
function mytheme_woo_add_custom_variation_fields_save( $post_id ) {
// Text Field
$woocommerce_text_field = $_POST['_variable_text_field'][ $post_id ];
update_post_meta( $post_id, '_variable_text_field', esc_attr( $woocommerce_text_field ) );
}
add_action( 'woocommerce_save_product_variation', 'mytheme_woo_add_custom_variation_fields_save', 10, 2 );
/*
* Display our example custom field above the summary on the Single Product Page
*/
function mytheme_display_woo_custom_fields() {
global $post;
$articleNumber = get_post_meta( $post->ID, '_variable_article_number', true );
$eanCode = get_post_meta( $post->ID, '_variable_ean_code', true );
$shelfLife = get_post_meta( $post->ID, '_variable_shelf_life', true );
if ( ! empty( $articleNumber ) ) {
echo '<div>Article number: ' . $articleNumber . '</div>';
}
if ( ! empty( $articleNumber ) ) {
echo '<div>EAN code: ' . $eanCode . '</div>';
}
if ( ! empty( $shelfLife ) ) {
echo '<div>Shelf life: ' . $shelfLife . '</div>';
}
}
add_action( 'woocommerce_single_product_summary', 'mytheme_display_woo_custom_fields', 15 );
The custom fields show correctly in the wordpress back-end and woocommerce template:
See here
But the problem is that custom fields don't update on changing the variation.
Thanks
If you are using WooCommerce 4, they have updated their product hook for variations.
Try using "woocommerce_update_product_variation".
I have been searching everywhere for an answer and just keep hitting road block after road block I have added custom variations fields in WooCommerce using http://www.remicorson.com/woocommerce-custom-fields-for-variations/ These fields save correctly when updating products.
I have installed WooCommerce Customer / Order CSV Export and have added a meta_field column placing the meta_key found in the code below.
Screenshot of the fields
However when I export the CSV file the fields are empty. Anyone have any experience with getting the custom variation field data to appear when exporting order data via CSV.
Listed below is the custom variation code being used. Any guidance would be greatly appreciated.
/**
* Create new fields for variations
*
*/
function variation_settings_fields( $loop, $variation_data, $variation ) {
// Text Field
woocommerce_wp_text_input(
array(
'id' => 'source_code[' . $variation->ID . ']',
'label' => __( 'Supplier', 'woocommerce' ),
'desc_tip' => 'true',
'value' => get_post_meta( $variation->ID, 'source_code', true )
)
);
woocommerce_wp_text_input(
array(
'id' => 'source_prod_id[' . $variation->ID . ']',
'label' => __( 'Supplier ID', 'woocommerce' ),
'desc_tip' => 'true',
'value' => get_post_meta( $variation->ID, 'source_prod_id', true ),
'custom_attributes' => array(
'step' => 'any',
'min' => '0'
)
)
);
woocommerce_wp_text_input(
array(
'id' => 'pkg_desc[' . $variation->ID . ']',
'label' => __( 'Package Size', 'woocommerce' ),
'desc_tip' => 'true',
'value' => get_post_meta( $variation->ID, 'pkg_desc', true ),
'custom_attributes' => array(
'step' => 'any',
'min' => '0'
)
)
);
woocommerce_wp_text_input(
array(
'id' => 'cost[' . $variation->ID . ']',
'label' => __( 'Cost', 'woocommerce' ),
'desc_tip' => 'true',
'value' => get_post_meta( $variation->ID, 'cost', true ),
'custom_attributes' => array(
'step' => 'any',
'min' => '0'
)
)
);
}
// Add Variation Settings
add_action( 'woocommerce_product_after_variable_attributes', 'variation_settings_fields', 10, 3 );
/**
* Save new fields for variations
*
*/
function save_variation_settings_fields( $post_id ) {
// Text Field
$text_field = $_POST['source_code'][ $post_id ];
if( ! empty( $text_field ) ) {
update_post_meta( $post_id, 'source_code', esc_attr( $text_field ) );
}
$number_field = $_POST['source_prod_id'][ $post_id ];
if( ! empty( $number_field ) ) {
update_post_meta( $post_id, 'source_prod_id', esc_attr( $number_field ) );
}
$number_field = $_POST['pkg_desc'][ $post_id ];
if( ! empty( $number_field ) ) {
update_post_meta( $post_id, 'pkg_desc', esc_attr( $number_field ) );
}
$number_field = $_POST['cost'][ $post_id ];
if( ! empty( $number_field ) ) {
update_post_meta( $post_id, 'cost', esc_attr( $number_field ) );
}
}
// Save Variation Settings
add_action( 'woocommerce_save_product_variation', 'save_variation_settings_fields', 10, 2 );
The WordPress plugin WooCommerce supports Custom Fields.
Custom Fields can be toggled under Screen Options:
However, these Custom Fields do no get segregated for product variations. There is only one set of Custom Fields that applies to all product variations in the WooCommerce interface, and this is inappropriate because different product variations may have different product MPNs, for example, which is one of the Custom Fields I have set up for myself.
The closest off-site solution I found does not link up to custom fields. The code, shown below, shows how one can set up input fields in the Product Variations interface. How can I modify the solution below to link up the Product Variations interface the custom fields?
This question is distinct from questions concerned with Advanced Custom Fields, as I am not using that plugin. Furthermore, at least one other similar question on Stack Overflow but I'm not proficient with PHP and I don't comprehend it, nor do I know if it is relevant - but I will point out that solution has not been accepted by the OP and I don't want to necropost there.
/**
* Create new fields for variations
*
*/
function variation_settings_fields( $loop, $variation_data, $variation ) {
// Text Field
woocommerce_wp_text_input(
array(
'id' => '_ean_code[' . $variation->ID . ']',
'label' => __( 'EAN-CODE', 'woocommerce' ),
'placeholder' => 'EAN-CODE',
'desc_tip' => 'true',
'description' => __( 'Enter your custom EAN code.', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_ean_code', true )
)
);
woocommerce_wp_text_input(
array(
'id' => '_stock_amsterdam[' . $variation->ID . ']',
'label' => __( 'Nr. of Stock in Amsterdam', 'woocommerce' ),
'desc_tip' => 'true',
'description' => __( 'Enter nr. of Stock in Amsterdam', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_stock_amsterdam', true ),
'custom_attributes' => array(
'step' => 'any',
'min' => '0'
)
)
);
woocommerce_wp_text_input(
array(
'id' => '_stock_den_bosch[' . $variation->ID . ']',
'label' => __( 'Nr. of Stock in Den Bosch', 'woocommerce' ),
'desc_tip' => 'true',
'description' => __( 'Enter nr. of Stock in Den Bosch', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_stock_den_bosch', true ),
'custom_attributes' => array(
'step' => 'any',
'min' => '0'
)
)
);
woocommerce_wp_text_input(
array(
'id' => '_stock_alkmaar[' . $variation->ID . ']',
'label' => __( 'Nr. of Stock in Alkmaar', 'woocommerce' ),
'desc_tip' => 'true',
'description' => __( 'Enter nr. of Stock in Alkmaar', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, '_stock_alkmaar', true ),
'custom_attributes' => array(
'step' => 'any',
'min' => '0'
)
)
);
}
/**
* Save new fields for variations
*
*/
function save_variation_settings_fields( $post_id ) {
// Text Field
$text_field = $_POST['_ean_code'][ $post_id ];
if( ! empty( $text_field ) ) {
update_post_meta( $post_id, '_ean_code', esc_attr( $text_field ) );
}
$number_field = $_POST['_stock_amsterdam'][ $post_id ];
if( ! empty( $number_field ) ) {
update_post_meta( $post_id, '_stock_amsterdam', esc_attr( $number_field ) );
}
$number_field = $_POST['_stock_den_bosch'][ $post_id ];
if( ! empty( $number_field ) ) {
update_post_meta( $post_id, '_stock_den_bosch', esc_attr( $number_field ) );
}
$number_field = $_POST['_stock_alkmaar'][ $post_id ];
if( ! empty( $number_field ) ) {
update_post_meta( $post_id, '_stock_alkmaar', esc_attr( $number_field ) );
}
}
// Save Variation Settings
add_action( 'woocommerce_save_product_variation', 'save_variation_settings_fields', 10, 2 );
// Add Variation Settings
add_action( 'woocommerce_product_after_variable_attributes', 'variation_settings_fields', 10, 3 );
OK, I'm stumped. I've searched and read several posts including the related post Checking products in cart based on category name woocommerce? from where I derived much of this code, and Woocommerce - Add filter to display (or hide) custom checkout field if product ID == # which is specific to Product IDs, not Category IDs.
I want to display the sdc_custom_checkout_field if, and only if, the target category ID (237 in this case) is in the cart.
I tried commenting out the sdc_custom_checkout_field function and using a simple test shown below, but kept getting "Nope!", so I assume the query is incorrect.
add_action( 'woocommerce_before_order_notes', 'sdc_custom_checkout_field' );
function sdc_custom_checkout_field( $checkout ) {
//Check if Product in Cart
//$product_in_cart = check_product_in_cart();
//Product is in cart so show additional fields
if ( $product_in_cart === true ) {
echo '<div id="my_custom_checkout_field"><h3>' . __( 'Duplicate Card Information' . '</h3><br>');
woocommerce_form_field( 'dupecard_location', array(
'type' => 'text',
'class' => array( 'dupecard-location form-row-wide' ),
'label' => __( 'Course Location' ),
), $checkout->get_value( 'dupecard_location' ) );
woocommerce_form_field( 'dupecard_instructor', array(
'type' => 'text',
'class' => array( 'dupecard-instructor form-row-wide' ),
'label' => __( 'Instructor Name' ),
), $checkout->get_value( 'dupecard_instructor' ) );
woocommerce_form_field( 'dupecard_requestor_name', array(
'type' => 'text',
'class' => array( 'dupecard-requestor-name form-row-wide' ),
'label' => __( 'Requestor Name' ),
), $checkout->get_value( 'dupecard_requestor_name' ) );
woocommerce_form_field( 'dupecard_requestor_email', array(
'type' => 'text',
'class' => array( 'dupecard-requestor-email form-row-wide' ),
'label' => __( 'Requestor Email' ),
), $checkout->get_value( 'dupecard_requestor_email' ) );
woocommerce_form_field( 'dupecard_requestor_phone', array(
'type' => 'text',
'class' => array( 'dupecard-requestor-phone form-row-wide' ),
'label' => __( 'Requestor Phone' ),
), $checkout->get_value( 'dupecard_requestor_phone' ) );
echo '</div>';
}
}
function check_product_in_cart() {
//Check to see if user has product in cart
global $woocommerce;
//assign default negative value
$product_in_cart = false;
// start cart items fetch loop
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
$terms = get_the_terms( $_product->id, 'product_cat' );
// second level loop search, in case some items have several categories
$cat_ids = array();
foreach ($terms as $term) {
$cat_ids[] = $term->term_id;
}
if(in_array(237, (array)$cat_ids)) {
//category is in cart!
$product_in_cart = true;
}
}
return $product_in_cart;
}
Here’s the test snippet:
if ($item_in_cart === true) {echo 'YES';}
else {echo 'Nope!';}
I also replaced
$item_in_cart
with
$product_in_cart
but it made no difference.
********** EDIT RESPONSE TO #PRAFULLA **********
#Prafulla - thanks for your input. I appreciate it. I modified my snippet as follows, incorporating yours, but was unable to get it to work. I'm a PHP newbie, so, no surprise. Do you have additional advice?
add_action( 'woocommerce_before_order_notes', 'sdc_custom_checkout_field' );
function sdc_custom_checkout_field( $checkout ) {
//Check if Product in Cart
$your_product_category = is_category_in_cart();
//Product is in cart so show additional fields
if ( $your_product_category === true ) {
echo '<div id="my_custom_checkout_field"><h3>' . __( 'Duplicate Card Information' . '</h3><br>');
woocommerce_form_field( 'dupecard_location', array(
'type' => 'text',
'class' => array( 'dupecard-location form-row-wide' ),
'label' => __( 'Course Location' ),
), $checkout->get_value( 'dupecard_location' ) );
woocommerce_form_field( 'dupecard_instructor', array(
'type' => 'text',
'class' => array( 'dupecard-instructor form-row-wide' ),
'label' => __( 'Instructor Name' ),
), $checkout->get_value( 'dupecard_instructor' ) );
woocommerce_form_field( 'dupecard_requestor_name', array(
'type' => 'text',
'class' => array( 'dupecard-requestor-name form-row-wide' ),
'label' => __( 'Requestor Name' ),
), $checkout->get_value( 'dupecard_requestor_name' ) );
woocommerce_form_field( 'dupecard_requestor_email', array(
'type' => 'text',
'class' => array( 'dupecard-requestor-email form-row-wide' ),
'label' => __( 'Requestor Email' ),
), $checkout->get_value( 'dupecard_requestor_email' ) );
woocommerce_form_field( 'dupecard_requestor_phone', array(
'type' => 'text',
'class' => array( 'dupecard-requestor-phone form-row-wide' ),
'label' => __( 'Requestor Phone' ),
), $checkout->get_value( 'dupecard_requestor_phone' ) );
echo '</div>';
}
}
function is_category_in_cart( $your_product_category = 237 ){
global $woocommerce;
$products_in_cart = $woocommerce->cart->get_cart();
$product_types_in_cart = array_column( $products_in_cart, 'data' );
//if ( $product_types_in_cart[0]->product_type == 'subscription' ) { this is what I have tested
if ( $product_types_in_cart[0]->product_cat == $your_product_category ) {
return true;
}
return $your_product_category;
}
After much work, research, and the assistance of some paid help on another website, this is the working result:
// Add the field to the checkout
add_action( 'woocommerce_before_order_notes', 'sdc_custom_checkout_field' );
function sdc_custom_checkout_field( $checkout ) {
if( check_product_category() ){
echo '<div id="sdc_checkout_field"><h3>' . __( 'Duplicate Card Information' . '</h3><br>');
woocommerce_form_field( 'dupecard_location', array(
'type' => 'text',
'required' => true,
'class' => array( 'dupecard-location form-row-wide' ),
'label' => __( 'Course Location' ),
), $checkout->get_value( 'dupecard_location' ) );
woocommerce_form_field( 'dupecard_instructor', array(
'type' => 'text',
'required' => true,
'class' => array( 'dupecard-instructor form-row-wide' ),
'label' => __( 'Instructor Name' ),
), $checkout->get_value( 'dupecard_instructor' ) );
woocommerce_form_field( 'dupecard_requestor_name', array(
'type' => 'text',
'required' => true,
'class' => array( 'dupecard-requestor-name form-row-wide' ),
'label' => __( 'Requestor Name' ),
), $checkout->get_value( 'dupecard_requestor_name' ) );
woocommerce_form_field( 'dupecard_requestor_email', array(
'type' => 'text',
'required' => true,
'class' => array( 'dupecard-requestor-email form-row-wide' ),
'label' => __( 'Requestor Email' ),
), $checkout->get_value( 'dupecard_requestor_email' ) );
woocommerce_form_field( 'dupecard_requestor_phone', array(
'type' => 'text',
'required' => true,
'class' => array( 'dupecard-requestor-phone form-row-wide' ),
'label' => __( 'Requestor Phone' ),
), $checkout->get_value( 'dupecard_requestor_phone' ) );
echo '</div>';
}
}
function check_product_category(){
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
if( is_category_in_cart( $product_id ) ){
return true;
}
}
return false;
}
function is_category_in_cart( $product_id ){
return has_term( 237,'product_cat', get_post( $product_id ) );
}
/*Save to DB as post meta*/
add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta' );
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['dupecard_location'] ) ) {
update_post_meta( $order_id, 'dupecard_location', sanitize_text_field( $_POST['dupecard_location'] ) );
}
if ( ! empty( $_POST['dupecard_instructor'] ) ) {
update_post_meta( $order_id, 'dupecard_instructor', sanitize_text_field( $_POST['dupecard_instructor'] ) );
}
if ( ! empty( $_POST['dupecard_requestor_name'] ) ) {
update_post_meta( $order_id, 'dupecard_requestor_name', sanitize_text_field( $_POST['dupecard_requestor_name'] ) );
}
if ( ! empty( $_POST['dupecard_requestor_email'] ) ) {
update_post_meta( $order_id, 'dupecard_requestor_email', sanitize_text_field( $_POST['dupecard_requestor_email'] ) );
}
if ( ! empty( $_POST['dupecard_requestor_phone'] ) ) {
update_post_meta( $order_id, 'dupecard_requestor_phone', sanitize_text_field( $_POST['dupecard_requestor_phone'] ) );
}
}
This is how I get the job done in my case , please try it and note where you need to give your input on this code as It is not written for direct use.
function is_category_in_cart( $your_product_category = null ){
global $woocommerce;
$products_in_cart = $woocommerce->cart->get_cart();
$product_types_in_cart = array_column( $products_in_cart, 'data' );
//if ( $product_types_in_cart[0]->product_type == 'subscription' ) { this is what I have tested
if ( $product_types_in_cart[0]->product_cat == $your_product_category ) {
return true;
}
}