2
votes

I am trying display if a variation of a product is already in a cart or not (in single product page). A simple comparing of the product id with products in cart object is not working for variable product as the variation id is being loaded using ajax.

Here is my code that works in case the product type is other than variable.

<?php
/*
 * Check if Product Already In Cart
*/
function woo_in_cart( $product_id ) {
    global $woocommerce;

    if ( !isset($product_id) ) {
        return false;
    }

    foreach( $woocommerce->cart->get_cart() as $cart_item ) {
        if ( $cart_item['product_id'] === $product_id ){
            return true;
        } else {
            return false;
        }
    }
}  

Is there any way to make it work without jQuery?

2
so just to clear this up: you want to check with php (in backend) the new products that are dynamically added in frontend (client) at the backend time? you have two solutions: 1. do it in frontend, 2. create an ajax and do it in backend (but will not be the initial time)Edwin
@Edwin What i intend to do is show a text after adding the product in cart or while browsing the product page (if the product is already in cart). The function works for simple products as the product id and cart item id are same. But in case of variable products, the variation id and product id ins't.Abhik

2 Answers

3
votes

Do you mean $product_id could be the ID of a variation? If so, you can just get the parent ID if it exists:

/*
 * Check if Product Already In Cart
 */
function woo_in_cart( $product_id ) {
    global $woocommerce;

    if ( ! isset( $product_id ) ) {
        return false;
    }

    $parent_id  = wp_get_post_parent_id( $product_id );
    $product_id = $parent_id > 0 ? $parent_id : $product_id;

    foreach ( $woocommerce->cart->get_cart() as $cart_item ) {
        if ( $cart_item['product_id'] === $product_id ) {
            return true;
        } else {
            return false;
        }
    }
}

If you mean your cart item is a variation, and $product_id is already the parent product ID, then your code should work already as is.

The $cart_item has 2 IDs: $cart_item['product_id'] and $cart_item['variation_id'].

So product_id will always be that of the parent product.

3
votes

To handle product variations outside single product pages (and simple products everywhere):

// Check if Product Already In Cart (Work with product variations too)
function woo_in_cart( $product_id = 0 ) {
    $found = false;
    if ( isset($product_id) || 0 == $product_id )
        return $found;

    foreach( WC()->cart->get_cart() as $cart_item ) {
        if ( $cart_item['data']->get_id() == $product_id )
            $found = true;
    }
    return $found;
}

To handle product variations inside single product pages, javascript is needed.

Here is an example that will show a custom message, when the selected variation is already in cart:

// Frontend: custom select field in variable products single pages
add_action( 'wp_footer', 'action_before_add_to_cart_button' );
function action_before_add_to_cart_button() {
    if( ! is_product() ) return;

    global $product;

    if( ! is_object($product) )
        $product = wc_get_product( get_the_id() );

    // Only for variable products when cart is not empty
    if( ! ( $product->is_type('variable') && ! WC()->cart->is_empty() ) ) return; // Exit

    $variation_ids_in_cart = array();

    // Loop through cart items
    foreach( WC()->cart->get_cart() as $cart_item ) {
        // Collecting product variation IDs if they are in cart for this variable product
        if ( $cart_item['variation_id'] > 0 && in_array( $cart_item['variation_id'], $product->get_children() ) )
            $variation_ids_in_cart[] = $cart_item['variation_id'];
    }

    // Only if a variation ID for this variable product is in cart
    if( sizeof($variation_ids_in_cart) == 0 ) return; // Exit

    // Message to be displayed (if the selected variation match with a variation in cart
    $message = __("my custom message goes here", "woocommerce");
    $message = '<p class="custom woocommerce-message" style="display:none;">'.$message.'</p>';

    // jQuery code
    ?>
    <script>
    (function($){
        // Utility function that check if variation match and display message
        function checkVariations(){
            var a = 'p.woocommerce-message.custom', b = false;
            $.each( <?php echo json_encode($variation_ids_in_cart); ?>, function( k, v ){
                if( $('input[name="variation_id"]').val() == v ) b = true;
            });
            if(b) $(a).show(); else $(a).hide();
        }

        // On load (when DOM is rendered)
        $('table.variations').after('<?php echo $message; ?>');
        setTimeout(function(){
            checkVariations();
        }, 800);

        // On live event: product attribute select fields "blur" event
        $('.variations select').blur( function(){
            checkVariations();
        });
    })(jQuery);
    </script>
    <?php
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

enter image description here