Search code examples
phpwordpresswoocommercevirtualcheckout

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


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?


Solution

  • 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.