Add WooCommerce custom checkout fields if there is only non virtual items - php

Have a script in my functions.php to show certain custom fields I created to appear at checkout, but some products do not need these fields to appear. So I assigned these as virtual and used this code to make these only appear on standard products:
add_action( 'woocommerce_before_order_notes', 'my_checkout_fields' );
function my_checkout_fields( $checkout ) {
$only_virtual = false;
foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
if ( ! $cart_item['data']->is_virtual() ) $only_virtual = true;
}
if( $only_virtual ) {
woocommerce_form_field( 'so_childs_name', array(
'type' => 'text',
'required' => 'true',
'class' => array('cname-class form-row-wide'),
'label' => __('Child's Name'),
), $checkout->get_value( 'so_childs_name' ));
}
It works.... occasionally.
Of course, I need it to work all the time, so why isn't it working or is there is a way instead of using only_virtual, can I just use an array of product ID's?

There are some mistake and a missing closing bracket in your code (if I have well understood). Try:
add_action( 'woocommerce_before_order_notes', 'my_checkout_fields' );
function my_checkout_fields( $checkout ) {
$has_virtual = false; // Initializing
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( $cart_item['data']->is_virtual() ) {
$has_virtual = true; // Stop the loop
break;
}
}
if( ! $has_virtual ) {
woocommerce_form_field( 'so_childs_name', array(
'type' => 'text',
'required' => 'true',
'class' => array('cname-class form-row-wide'),
'label' => __('Child's Name'),
), $checkout->get_value( 'so_childs_name' ) );
}
}
Code goes in functions.php file of the active child theme (or active theme). It should work.

Related

Woocommerce add order meta from checkbox [duplicate]

Am using the snippet below to show a custom checkbox for all products but would like to hide/not show it if product with ID 32 is in cart. How do i modify this code to achieve that? Thanks in advance.
add_action( 'woocommerce_review_order_before_submit', 'bbloomer_add_checkout_privacy_policy', 9 );
function bbloomer_add_checkout_privacy_policy() {
woocommerce_form_field( 'privacy_policy', array(
'type' => 'checkbox',
'class' => array('form-row privacy'),
'label_class' => array('woocommerce-form__label woocommerce-form__label-for-checkbox checkbox'),
'input_class' => array('woocommerce-form__input woocommerce-form__input-checkbox input-checkbox'),
'required' => true,
'label' => 'I\'ve read and accept the Privacy Policy',
));
}
// Show notice if customer does not tick
add_action( 'woocommerce_checkout_process', 'bbloomer_not_approved_privacy' );
function bbloomer_not_approved_privacy() {
if ( ! (int) isset( $_POST['privacy_policy'] ) ) {
wc_add_notice( __( 'Please acknowledge the Privacy Policy' ), 'error' );
}
}
Before you actually show the checkbox field, you will first have to go through the cart to see if the productID is NOT present.
Same for the validation, as it is a required field and would otherwise still be a required field, even though it is not present.
So you get:
// Function to check if a certain product ID is in cart
function is_product_in_cart() {
// Check if product in cart
// Multiple product IDs can be entered, separated by a comma
$targeted_ids = array( 32, 1234, 5678 );
// Flag no product in cart
$flag = false;
// WC Cart NOT null
if ( ! is_null( WC()->cart ) ) {
// Loop through cart items
foreach( WC()->cart->get_cart() as $cart_item ) {
// Check cart item for defined product Ids
if ( in_array( $cart_item['product_id'], $targeted_ids ) ) {
// Product is in cart
$flag = true;
// Break loop
break;
}
}
}
return $flag;
}
// Add field
function action_woocommerce_review_order_before_submit() {
// NOT true
if ( ! is_product_in_cart() ) {
// Add checkbox
woocommerce_form_field( 'privacy_policy', array(
'type' => 'checkbox',
'class' => array( 'form-row privacy' ),
'label_class' => array( 'woocommerce-form__label woocommerce-form__label-for-checkbox checkbox' ),
'input_class' => array( 'woocommerce-form__input woocommerce-form__input-checkbox input-checkbox' ),
'required' => true,
'label' => 'I\'ve read and accept the Privacy Policy',
));
}
}
add_action( 'woocommerce_review_order_before_submit', 'action_woocommerce_review_order_before_submit', 9 );
// Validate
function action_woocommerce_checkout_process() {
// NOT true
if ( ! is_product_in_cart() ) {
// NOT isset
if ( ! isset( $_POST['privacy_policy'] ) ) {
wc_add_notice( __( 'Please acknowledge the Privacy Policy', 'woocommerce' ), 'error' );
}
}
}
add_action( 'woocommerce_checkout_process', 'action_woocommerce_checkout_process', 10, 0 );
// Save field
function action_woocommerce_checkout_create_order( $order, $data ) {
// Isset
if ( isset( $_POST['privacy_policy'] ) ) {
$order->update_meta_data( 'privacy_policy', sanitize_text_field( $_POST['privacy_policy'] ) );
}
}
add_action( 'woocommerce_checkout_create_order', 'action_woocommerce_checkout_create_order', 10, 2 );

Woocommerce - show checkbox at checkout for certain products and/or categories

I want to show a custom checkbox during checkout that will only show for certain SKUs or Product categories. I already have this code that shows the checkbox on all checkout pages
add_action( 'woocommerce_review_order_before_submit', 'bt_add_checkout_checkbox', 10 );
/**
* Add WooCommerce additional Checkbox checkout field
*/
function bt_add_checkout_checkbox() {
woocommerce_form_field( 'checkout_checkbox', array( // CSS ID
'type' => 'checkbox',
'class' => array('form-row mycheckbox'), // CSS Class
'label_class' => array('woocommerce-form__label woocommerce-form__label-for-checkbox checkbox'),
'input_class' => array('woocommerce-form__input woocommerce-form__input-checkbox input-checkbox'),
'required' => true, // Mandatory or Optional
'label' => 'Custom label', // Label and Link
));
}
add_action( 'woocommerce_checkout_process', 'bt_add_checkout_checkbox_warning' );
/**
* Alert if checkbox not checked
*/
function bt_add_checkout_checkbox_warning() {
if ( ! (int) isset( $_POST['checkout_checkbox'] ) ) {
wc_add_notice( __( 'Please acknowledge the Checkbox' ), 'error' );
}
}
I don't know much about PHP but I think I must use $cart_item and $product within a foreach loop and an if statement but I'm quite lost with this part, my logic says it would be something like this:
function bt_add_checkout_checkbox() {
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ){
$product = $cart_item['data'];
$sku = WC()->cart->get_sku($product);
if ($sku == 'SA300ARS'){
woocommerce_form_field( 'checkout_checkbox', array( // CSS ID
'type' => 'checkbox',
'class' => array('form-row mycheckbox'), // CSS Class
'label_class' => array('woocommerce-form__label woocommerce-form__label-for-checkbox checkbox'),
'input_class' => array('woocommerce-form__input woocommerce-form__input-checkbox input-checkbox'),
'required' => true, // Mandatory or Optional
'label' => 'I acknowledge that my product can take up to 24 hours to be delivered. (Unless the description says otherwise)', // Label and Link
));
}
}
}
You're going in the right direction. You just need to modify the code like this:
add_action( 'woocommerce_review_order_before_submit', 'bt_add_checkout_checkbox', 10 );
/**
* Add WooCommerce additional Checkbox checkout field
*/
function bt_add_checkout_checkbox() {
//Check if wooCommerce is activated
if ( class_exists( 'WooCommerce' ) ) {
//Define SKUs you want to check for
$checkSKUs = ['sku1', 'sku2', 'sku3'];
//Grab all the SKUs in cart
$skus = array();
foreach( WC()->cart->get_cart() as $cart_item ) {
array_push($skus, $cart_item['data']->get_sku());
}
//Check if anything matches in both
$matchingResult = array_intersect($checkSKUs,$skus);
if (count($matchingResult) > 0) {
//If at least 1 SKU matches then generate checkout field
woocommerce_form_field( 'checkout_checkbox', array( // CSS ID
'type' => 'checkbox',
'class' => array('form-row mycheckbox'), // CSS Class
'label_class' => array('woocommerce-form__label woocommerce-form__label-for-checkbox checkbox'),
'input_class' => array('woocommerce-form__input woocommerce-form__input-checkbox input-checkbox'),
'required' => true, // Mandatory or Optional
'label' => 'I acknowledge that my product can take up to 24 hours to be delivered. (Unless the description says otherwise)', // Label and Link
));
}
}
}
add_action( 'woocommerce_checkout_process', 'bt_add_checkout_checkbox_warning' );
/**
* Alert if checkbox not checked
*/
function bt_add_checkout_checkbox_warning() {
if ( ! (int) isset( $_POST['checkout_checkbox'] ) ) {
wc_add_notice( __( 'Please acknowledge the Checkbox' ), 'error' );
}
}
I believe this should work. If not then let me know.
I've added comments for your understanding.

Save Woocommerce cart item custom data as order item meta data displaying it on orders and emails

Regarding Woocommerce. I have custom data that I am adding to the cart. In the functions.php file, I have the following function.
// Display cart item custom data in cart and checkout pages
add_filter( 'woocommerce_get_item_data', 'display_cart_item_custom_on_cart_and_checkout', 10, 2 );
function display_cart_item_custom_on_cart_and_checkout( $cart_item_data, $cart_item ){
if( isset($cart_item['custom_data']['label0']) && isset($cart_item['custom_data']['value0']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label0'],
'value' => $cart_item['custom_data']['value0'],
);
}
if( isset($cart_item['custom_data']['label']) && isset($cart_item['custom_data']['value']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label'],
'value' => $cart_item['custom_data']['value'],
);
}
if( isset($cart_item['custom_data']['label2']) && isset($cart_item['custom_data']['value2']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label2'],
'value' => $cart_item['custom_data']['value2'],
);
}
if( isset($cart_item['custom_data']['label3']) && isset($cart_item['custom_data']['value3']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label3'],
'value' => $cart_item['custom_data']['value3'],
);
}
if( isset($cart_item['custom_data']['label4']) && isset($cart_item['custom_data']['value4']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label4'],
'value' => $cart_item['custom_data']['value4'],
);
}
if( isset($cart_item['custom_data']['label5']) && isset($cart_item['custom_data']['value5']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label5'],
'value' => $cart_item['custom_data']['value5'],
);
}
if( isset($cart_item['custom_data']['label6']) && isset($cart_item['custom_data']['value6']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label6'],
'value' => $cart_item['custom_data']['value6'],
);
}
if( isset($cart_item['custom_data']['label7']) && isset($cart_item['custom_data']['value7']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label7'],
'value' => $cart_item['custom_data']['value7'],
);
}
if( isset($cart_item['custom_data']['label8']) && isset($cart_item['custom_data']['value8']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label8'],
'value' => $cart_item['custom_data']['value8'],
);
}
if( isset($cart_item['custom_data']['label9']) && isset($cart_item['custom_data']['value9']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label9'],
'value' => $cart_item['custom_data']['value9'],
);
}
if( isset($cart_item['custom_data']['label10']) && isset($cart_item['custom_data']['value10']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label10'],
'value' => $cart_item['custom_data']['value10'],
);
}
return $cart_item_data;
}
This works and the custom data is shown in the cart. However, the custom data does not show on the order and order email. I have seen, on Stackoverflow several answers that provide solutions to this problem but I cannot make them work for my situation. The solutions that I reference are.
Save and display order item custom meta data in Woocommerce
Display and save added custom cart item data on Woocommerce Cart, Checkout and Orders
Can anybody kindly show me what "my" function should be?
Thank you.
First you can optimize and compact your function this way:
// Display cart item custom data in cart and checkout pages
add_filter( 'woocommerce_get_item_data', 'display_cart_item_custom_on_cart_and_checkout', 10, 2 );
function display_cart_item_custom_on_cart_and_checkout( $cart_item_data, $cart_item ){
$keys = array('0','','2','3','4','5','6','7','8','9','10'); // Fields numbers part keys array
// Loop through Fields numbers part keys array
foreach( $keys as $key ) {
if( isset($cart_item['custom_data']['label'.$key]) && isset($cart_item['custom_data']['value'.$key]) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label'.$key],
'value' => $cart_item['custom_data']['value'.$key],
);
}
}
return $cart_item_data;
}
Then to save all your custom cart item data as custom order item meta data and display it everywhere on orders and emails, use the following:
// Save cart item custom data as order item meta data and display it everywhere in Orders and email notifications
add_action('woocommerce_checkout_create_order_line_item', 'save_as_custom_order_item_meta_data', 10, 4 );
function save_as_custom_order_item_meta_data( $item, $cart_item_key, $values, $order ) {
$keys = array('0','','2','3','4','5','6','7','8','9','10'); // Fields numbers part keys array()
// Loop through Fields numbers part keys array
foreach( $keys as $key ) {
if( isset( $values['custom_data']['label'.$key] ) && isset( $values['custom_data']['value'.$key] ) ) {
$item->update_meta_data( $values['custom_data']['label'.$key], $values['custom_data']['value'.$key] );
}
}
}
Code goes in functions.php file of the active child theme (or active theme). It should works.

Check for multiple product ID's in cart in WooCommerce

I am using the following code to check if a product ID is in the cart, and if so, add extra checkout fields:
add_action('woocommerce_after_order_notes', 'conditional_checkout_field');
function conditional_checkout_field( $checkout ) {
echo '<div id="conditional_checkout_field">';
$product_id = 326;
$product_cart_id = WC()->cart->generate_cart_id( $product_id );
$in_cart = WC()->cart->find_product_in_cart( $product_cart_id );
// Check if the product is in the cart and show the custom field if it is
if ($in_cart ) {
echo '<h3>'.__('Products in your cart require the following information').'</h3>';
woocommerce_form_field( 'custom_field_license', array(
'type' => 'text',
'class' => array('my-field-class form-row-wide'),
'label' => __('License Number'),
'placeholder' => __('Placeholder to help describe what you are looking for'),
), $checkout->get_value( 'custom_field_license' ));
}
}
This works just fine. However, how do I check for multiple product ID's in the cart? For instance, if product ID 326 or 245 are in the cart, show the conditional checkout fields? I feel like it is probably something simple, but I'm not sure how to go about doing it.
I have make some changes in your function to get it work for many product IDs. Also I have added the required option to the field. So your code sould be something like:
add_action('woocommerce_after_order_notes', 'conditional_checkout_field', 10, 1);
function conditional_checkout_field( $checkout ) {
// Set here your product IDS (in the array)
$product_ids = array( 37, 53, 70 );
$is_in_cart = false;
// Iterating through cart items and check
foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item )
if( in_array( $cart_item['data']->get_id(), $product_ids ) ){
$is_in_cart = true; // We set it to "true"
break; // At east one product, we stop the loop
}
// If condition match we display the field
if( $is_in_cart ){
echo '<div id="conditional_checkout_field">
<h3 class="field-license-heading">'.__('Products in your cart require the following information').'</h3>';
woocommerce_form_field( 'custom_field_license', array(
'type' => 'text',
'class' => array('my-field-class form-row-wide'),
'required' => true, // Added required
'label' => __('License Number'),
'placeholder' => __('Placeholder to help describe what you are looking for'),
), $checkout->get_value( 'custom_field_license' ));
echo '</div>';
}
}
Code goes in function.php file of your active child theme (active theme or in any plugin file).
This code is tested and works.

Fatal error: Call to a member function get_cart_contents_count() on a non-object in /functions.php on line 413

on line 413 $product_count =
$woocommerce->cart->get_cart_contents_count();
function wc_sell_only_states( $states ) {
// set our flag to be false until we find a product in that category
$cat_check = false;
global $woocommerce;
ob_start();
//==========================================AAAAAAAAAAAAAAAAA
$product_count = $woocommerce->cart->get_cart_contents_count();
if($product_count > 0){
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $cart_item ) { //foreach
$product = $cart_item['data'];
// replace 'membership' with your category's slug
if ( has_term( 'VIP', 'product_tag', $product->id ) ) {//search product_cat
$cat_check = true;
// break because we only need one "true" to matter here
//////////////////////////////////////////////////////////////////////////////////////
if (!function_exists('soosti_add_checkout_content')) {
function soosti_add_checkout_content() { // skyverge function
echo '<p style="color:#F31114">Attention: In your shopping cart hava Special product that only shipping to <b>California</b>...</p>';
}//end skyverge function
}
add_action( 'woocommerce_before_checkout_form', 'soosti_add_checkout_content', 12 );
//-------------------------
//---------------------------
if (!function_exists('woo_override_checkout_fields')) {
function woo_override_checkout_fields( $fields ) { // woo_override_checkout_fields Function
$fields['billing']['billing_country'] = array(
'type' => 'select',
'label' => __('Country', 'woocommerce'),
'options' => array('US' => 'United States(US)')
);
$fields['billing']['billing_state'] = array(
'type' => 'select',
'label' => __('State', 'woocommerce'),
'options' => array('CA' => 'California(CA)')
);
return $fields;
} //end woo_override_checkout_fields Function
}
add_filter( 'woocommerce_checkout_fields' , 'woo_override_checkout_fields' );
how to fix this error?
when I run this code I get a fatal error. I think
$woocommerce->cart->get_cart_contents_count();
make empty.
so how do I resolve this error? please help me
Finally I found answer for
Fatal error: Call to a member function get_cart_contents_count() on a
non-object
function a000_remove_bundles_counting(){
global $woocommerce_bundles;
remove_filter( 'woocommerce_cart_contents_count',
array( $woocommerce_bundles->display, 'woo_bundles_cart_contents_count' ) );
}
add_action( 'init', 'a000_remove_bundles_counting' );
disable the Bundles filter before simultaneously adding own via
d000_cart_contents_count
function d000_cart_contents_count( $count ) {
global $woocommerce;
$cat_check = false;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $cart_item ) { //foreach
$product = $cart_item['data'];
if ( has_term( 'tv', 'product_tag', $product->id ) ) {//search product_cat
$cat_check = true;
// break because we only need one "true" to matter here
if (!function_exists('woo_override_checkout_fields')) {
function woo_override_checkout_fields( $fields ) { // woo_override_checkout_fields Function
$fields['billing']['billing_country'] = array(
'type' => 'select',
'label' => __('Country', 'woocommerce'),
'options' => array('US' => 'United States(US)')
);
$fields['billing']['billing_state'] = array(
'type' => 'select',
'label' => __('State', 'woocommerce'),
'options' => array('CA' => 'California(CA)')
);
return $fields;
} //end woo_override_checkout_fields Function
}
add_filter( 'woocommerce_checkout_fields' , 'woo_override_checkout_fields' );
} // end search product_cat
}// end foreach
return $count;
}
add_filter( 'woocommerce_cart_contents_count',
'd000_cart_contents_count' );

Categories