How to display custom WooCommerce billing fields based on product IDs

60 Views Asked by At

I want to show/hide custom fields on the checkout page based on Product IDs. Therefore, I am using the following code:

function display_custom_checkout_fields_based_on_product( $fields ) {
    $product_ids_participating_location = array( 5503 );
    $product_ids_toxicology = array( 5453, 5454, 5455 );
    $product_ids_artificial_intelligence = array( 5453, 5454, 5455, 5496 );

    $current_product_id = 0;

    if ( WC()->cart && WC()->cart->get_cart() ) {
        foreach ( WC()->cart->get_cart() as $cart_item ) {
            $product = $cart_item['data'];
            if ( $product && is_a( $product, 'WC_Product' ) ) {
                $current_product_id = $product->get_id();
                break;
            }
        }
    }

    unset( $fields['billing_participating_location'] );
    unset( $fields['billing_toxicology'] );
    unset( $fields['billing_artificial_intelligence'] );

    if ( in_array( $current_product_id, $product_ids_participating_location ) ) {
        $fields['billing_participating_location'] = array(
            'label'    => 'Participating Location',
            'required' => true,
            'class'    => array( 'form-row-wide' ),
            'clear'    => true,
        );
    }

    if ( in_array( $current_product_id, $product_ids_toxicology ) ) {
        $fields['billing_toxicology'] = array(
            'label'    => 'Toxicology',
            'required' => true,
            'class'    => array( 'form-row-wide' ),
            'clear'    => true,
        );
    }

    if ( in_array( $current_product_id, $product_ids_artificial_intelligence ) ) {
        $fields['billing_artificial_intelligence'] = array(
            'label'    => 'Artificial Intelligence',
            'required' => true,
            'class'    => array( 'form-row-wide' ),
            'clear'    => true,
        );
    }

    return $fields;
}

add_filter( 'woocommerce_checkout_fields', 'display_custom_checkout_fields_based_on_product' );

But it's not working as expected.

I want to show each field only for the related product IDs in the defined array.

Any help will be greatly appreciated.

2

There are 2 best solutions below

0
LoicTheAztec On BEST ANSWER

There are some mistakes, unnecessary and missing things in your code:

Use the following revisited code instead:

add_filter( 'woocommerce_checkout_fields', 'display_custom_checkout_fields_based_on_cart_items' );
function display_custom_checkout_fields_based_on_cart_items( $fields ) {
    $participating_location_ids  = array( 5503 );
    $toxicology_ids              = array( 5453, 5454, 5455 );
    $artificial_intelligence_ids = array( 5453, 5454, 5455, 5496 );

    $item_ids = array(); // Initializing

    // Collect cart items product IDs
    foreach ( WC()->cart->get_cart() as $cart_item ) {
        $item_ids[] = $cart_item['product_id'];

        if ( $cart_item['variation_id'] > 0 ) {
            $item_ids[] = $cart_item['variation_id'];
        }
    }

    // Check Ids to display 'billing_participating_location' field
    if ( count( array_intersect( $item_ids, $participating_location_ids ) ) > 0 ) {
        $fields['billing']['billing_participating_location'] = array(
            'label'    => 'Participating Location',
            'required' => true,
            'class'    => array( 'form-row-wide' ),
            'clear'    => true,
        );
    }
    // Check Ids to display 'billing_toxicology' field
    if ( count( array_intersect( $item_ids, $toxicology_ids ) ) > 0 ) {
        $fields['billing']['billing_toxicology'] = array(
            'label'    => 'Toxicology',
            'required' => true,
            'class'    => array( 'form-row-wide' ),
            'clear'    => true,
        );
    }
    // Check Ids to display 'billing_artificial_intelligence' field
    if ( count( array_intersect( $item_ids, $artificial_intelligence_ids ) ) > 0 ) {
        $fields['billing']['billing_artificial_intelligence'] = array(
            'label'    => 'Artificial Intelligence',
            'required' => true,
            'class'    => array( 'form-row-wide' ),
            'clear'    => true,
        );
    }

    return $fields;
}

Code goes in functions.php file of your child theme (or in a plugin). Tested and works.

0
RP-90 On

Your code tries to determine the current product ID based on the items in the cart. This approach assumes that only one product can be in the cart at a time. If you have multiple products in the cart, it will only use the product ID of the first item. To handle multiple products, you should collect all the product IDs in an array and then apply your conditional logic.

Here's a modified version of your code:

function display_custom_checkout_fields_based_on_product( $fields ) {
    $product_ids_participating_location = array( 5503 );
    $product_ids_toxicology = array( 5453, 5454, 5455 );
    $product_ids_artificial_intelligence = array( 5453, 5454, 5455, 5496 );

    $current_product_ids = array();

    if ( WC()->cart && WC()->cart->get_cart() ) {
        foreach ( WC()->cart->get_cart() as $cart_item ) {
            $product = $cart_item['data'];
            if ( $product && is_a( $product, 'WC_Product' ) ) {
                $current_product_ids[] = $product->get_id();
            }
        }
    }

    // Remove fields by default
    unset( $fields['billing_participating_location'] );
    unset( $fields['billing_toxicology'] );
    unset( $fields['billing_artificial_intelligence'] );

    // Check if fields should be added based on current product IDs
    if ( array_intersect( $current_product_ids, $product_ids_participating_location ) ) {
        $fields['billing_participating_location'] = array(
            'label'    => 'Participating Location',
            'required' => true,
            'class'    => array( 'form-row-wide' ),
            'clear'    => true,
        );
    }

    if ( array_intersect( $current_product_ids, $product_ids_toxicology ) ) {
        $fields['billing_toxicology'] = array(
            'label'    => 'Toxicology',
            'required' => true,
            'class'    => array( 'form-row-wide' ),
            'clear'    => true,
        );
    }

    if ( array_intersect( $current_product_ids, $product_ids_artificial_intelligence ) ) {
        $fields['billing_artificial_intelligence'] = array(
            'label'    => 'Artificial Intelligence',
            'required' => true,
            'class'    => array( 'form-row-wide' ),
            'clear'    => true,
        );
    }

    return $fields;
}

add_filter( 'woocommerce_checkout_fields', 'display_custom_checkout_fields_based_on_product' );

With this, it collect all current product IDs in the $current_product_ids array and then uses array_intersect to determine if each field should be added based on the product IDs.