Whisper
Whisper

Reputation: 23

Foreach loop stops running after finding a single item

I have a conditional field remover that works perfectly fine with ids but the moment i try to run it with categories it stops after getting a result.

I have used this tutorial as an guide line:

<?php
    /*=============Conditional field remover===========*/
    //Cart check
    function wc_ninja_product_is_in_the_cart() {
        /*p1 products*/
        $p1_cat = array( 'metal', 'wood');
        /*p2 products*/
        $p2_cat = array('bubblewrap');

    // Products currently in the cart
    $cart_ids = array();
    $cart_categories = array();
    //Declaring var
    $p1 = false;
    $p2 = false;
    //creating an array
    foreach( WC()->cart->get_cart() as $cart_item_key => $values ) {
        $cart_product = $values['data'];
        $cart_ids[] = $cart_product->id;
    }
    //filling array 
    foreach( $cart_ids as $id ) {
        $products_categories = get_the_terms( $id, 'product_cat');
    }
    //filling category
    foreach ($products_categories as $products_category)    {
        //Check
        if (in_array($products_category->slug, $p1_cat)) {
            $p1 = true;//Result
        }
        if (in_array($products_category->slug, $p2_cat)) {
            $p2 = true;//Result
        }
        $cart_categories[] = $products_category->slug;
    }
    //Returns result to function
    return array($p1, $p2);
}
//Field Remover
function wc_ninja_remove_checkout_field( $fields ) {
    //Gets value from function and places them in the array !PHP 7 reverses order!
    list($p1, $p2) = wc_ninja_product_is_in_the_cart();
    var_dump(wc_ninja_product_is_in_the_cart());
    //If check came back false it will remove the field in question
    if ( $p1 == false ) {
        //removes Field domain name
        unset( $fields['billing']['Field_1'] );
    }
    if ( $p2 == false ) {
        //Removes Field office_emails
        unset( $fields['billing']['Field_2'] );
    }
    //Return unset result
    return $fields;
}
add_filter( 'woocommerce_checkout_fields' , 'wc_ninja_remove_checkout_field' );

The code above will result in only showing Field_1 if two products are added (in the test case metal box cat=>metal and packing material cat=>bubblewrap, i already checked the spelling. other things i did was a var_dump of the array which gave me: [0]=> string(5) "metal"

I tried to make the array go through with a i++; it did change the position to [x] where x is the number of products -1. as i mentioned before i made a version that uses an ID which works fine just not practical in a big store so i know the works return array works fine.

I didn't follow the tutorial to the dot and closed one of the foreach loops too early resulting in only running the check one time. it was supposed to be like that but i had a } above //filling category resulting in cutting off the loop.

foreach( $cart_ids as $id ) {
    $products_categories = get_the_terms( $id, 'product_cat');
    //filling category
    foreach ($products_categories as $products_category)    {

Upvotes: 2

Views: 200

Answers (1)

LoicTheAztec
LoicTheAztec

Reputation: 254378

UPDATE:

This code is working, I have tested it.
Where is the code that you are using to create that 2 checkout custom fields?
I think that is your main problem Here. And the tutorial you are using is a little outdated and complicated for nothing. Here is the official WooCommerce tutorial for checkout fields

You should update your question whith that missing code and tell clearly what you want to do with that 2 checkout custom fields (and give some details about them).

To make your field remover function working with categories, you should use has_term() function as conditions, this way:

// Checkout Field Remover
add_filter( 'woocommerce_checkout_fields' , 'custom_cats_remove_checkout_field' );
function custom_cats_remove_checkout_field( $fields ) {
    // Initialising variables
    $cat1_found = false;
    $cat2_found = false;
    
    // Iterating throuh each cart item
    foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
        // Cart item_id
        $cart_item_id = $cart_item['data']->id;
        
        // For first categories group
        if(has_term( array( 'metal', 'wood'), 'product_cat', $cart_item_id)){
            $cat1_found = true;
        }
        
        // For the second category
        if(has_term( 'bubblewrap', 'product_cat', $cart_item_id)){
            $cat2_found = true;
        }
    }
    //If check came back false it will remove the field in question
    if ( $cat1_found ) {
        // Removes Field domain name
        unset( $fields['billing']['Field_1'] );
    }
    if ( $cat2_found ) {
        //Removes Field office_emails
        unset( $fields['billing']['Field_2'] );
    }
    //Return unset result
    return $fields;
}

Code goes in function.php file of your active child theme (or theme). Or also in any plugin php files.

Upvotes: 1

Related Questions