简体   繁体   中英

Adding multiple items to WooCommerce cart at once

I have 3 IDs of the different items that I want to add to my shopping cart. I could use https://url.com/shop/cart/?add-to-cart=3001 but when I want to add 3 items I can't do it. Is there any function/script I can add to add this ability to my shopping website?

I tried to add an & after the add-to-cart and tried to add a new value but GETs get overridden right?: https://url.com/shop/cart/?add-to-cart=3001&add-to-cart=2002&add-to-cart=1001

I found the answer!

Simply add the following script to your theme's functions.php:

function woocommerce_maybe_add_multiple_products_to_cart() {
// Make sure WC is installed, and add-to-cart qauery arg exists, and contains at least one comma.
if ( ! class_exists( 'WC_Form_Handler' ) || empty( $_REQUEST['add-to-cart'] ) || false === strpos( $_REQUEST['add-to-cart'], ',' ) ) {
    return;
}

// Remove WooCommerce's hook, as it's useless (doesn't handle multiple products).
remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 );

$product_ids = explode( ',', $_REQUEST['add-to-cart'] );
$count       = count( $product_ids );
$number      = 0;

foreach ( $product_ids as $product_id ) {
    if ( ++$number === $count ) {
        // Ok, final item, let's send it back to woocommerce's add_to_cart_action method for handling.
        $_REQUEST['add-to-cart'] = $product_id;

        return WC_Form_Handler::add_to_cart_action();
    }

    $product_id        = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $product_id ) );
    $was_added_to_cart = false;
    $adding_to_cart    = wc_get_product( $product_id );

    if ( ! $adding_to_cart ) {
        continue;
    }

    $add_to_cart_handler = apply_filters( 'woocommerce_add_to_cart_handler', $adding_to_cart->product_type, $adding_to_cart );

    /*
     * Sorry.. if you want non-simple products, you're on your own.
     *
     * Related: WooCommerce has set the following methods as private:
     * WC_Form_Handler::add_to_cart_handler_variable(),
     * WC_Form_Handler::add_to_cart_handler_grouped(),
     * WC_Form_Handler::add_to_cart_handler_simple()
     *
     * Why you gotta be like that WooCommerce?
     */
    if ( 'simple' !== $add_to_cart_handler ) {
        continue;
    }

    // For now, quantity applies to all products.. This could be changed easily enough, but I didn't need this feature.
    $quantity          = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( $_REQUEST['quantity'] );
    $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );

    if ( $passed_validation && false !== WC()->cart->add_to_cart( $product_id, $quantity ) ) {
        wc_add_to_cart_message( array( $product_id => $quantity ), true );
    }
}
}

 // Fire before the WC_Form_Handler::add_to_cart_action callback.
 add_action( 'wp_loaded',        'woocommerce_maybe_add_multiple_products_to_cart', 15 );

And then you can simply use http://shop.com/shop/cart/?add-to-cart=3001,3282 to add multiple items at once. Put a comma between different IDs.

Thanks to dsgnwrks for the solution.

In case anyone else comes by looking for this function like I did. I updated the top comment's code allowing it to work with woocommerce 3.5.3

    // adds support for multi add to cart for 3rd party cart plugin
function woocommerce_maybe_add_multiple_products_to_cart() {
    // Make sure WC is installed, and add-to-cart qauery arg exists, and contains at least one comma.
    if ( ! class_exists( 'WC_Form_Handler' ) || empty( $_REQUEST['add-to-cart'] ) || false === strpos( $_REQUEST['add-to-cart'], ',' ) ) {
        return;
    }

    // Remove WooCommerce's hook, as it's useless (doesn't handle multiple products).
    remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 );

    $product_ids = explode( ',', $_REQUEST['add-to-cart'] );
    $count       = count( $product_ids );
    $number      = 0;

    foreach ( $product_ids as $product_id ) {
        if ( ++$number === $count ) {
            // Ok, final item, let's send it back to woocommerce's add_to_cart_action method for handling.
            $_REQUEST['add-to-cart'] = $product_id;

            return WC_Form_Handler::add_to_cart_action();
        }

        $product_id        = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $product_id ) );
        $was_added_to_cart = false;

        $adding_to_cart    = wc_get_product( $product_id );

        if ( ! $adding_to_cart ) {
            continue;
        }

        // only works for simple atm
        if ( $adding_to_cart->is_type( 'simple' ) ) {

            // quantity applies to all products atm
            $quantity          = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( $_REQUEST['quantity'] );
            $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );

            if ( $passed_validation && false !== WC()->cart->add_to_cart( $product_id, $quantity ) ) {
                wc_add_to_cart_message( array( $product_id => $quantity ), true );
            }

        }
    }
}
add_action( 'wp_loaded', 'woocommerce_maybe_add_multiple_products_to_cart', 15 );

Thanks to @thatgerhard and dsgnwrks
I found a solution for support variations:

function woocommerce_maybe_add_multiple_products_to_cart() {
  // Make sure WC is installed, and add-to-cart qauery arg exists, and contains at least one comma.
  if ( ! class_exists( 'WC_Form_Handler' ) || empty( $_REQUEST['add-to-cart'] ) || false === strpos( $_REQUEST['add-to-cart'], ',' ) ) {
      return;
  }

  remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 );

  $product_ids = explode( ',', $_REQUEST['add-to-cart'] );
  $count       = count( $product_ids );
  $number      = 0;

  foreach ( $product_ids as $product_id ) {
      if ( ++$number === $count ) {
          // Ok, final item, let's send it back to woocommerce's add_to_cart_action method for handling.
          $_REQUEST['add-to-cart'] = $product_id;

          return WC_Form_Handler::add_to_cart_action();
      }

      $product_id        = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $product_id ) );
      $was_added_to_cart = false;

      $adding_to_cart    = wc_get_product( $product_id );

      if ( ! $adding_to_cart ) {
          continue;
      }

      if ( $adding_to_cart->is_type( 'simple' ) ) {

          // quantity applies to all products atm
          $quantity          = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( $_REQUEST['quantity'] );
          $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );

          if ( $passed_validation && false !== WC()->cart->add_to_cart( $product_id, $quantity ) ) {
              wc_add_to_cart_message( array( $product_id => $quantity ), true );
          }

      } else {

          $variation_id       = empty( $_REQUEST['variation_id'] ) ? '' : absint( wp_unslash( $_REQUEST['variation_id'] ) );
          $quantity           = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( wp_unslash( $_REQUEST['quantity'] ) ); // WPCS: sanitization ok.
          $missing_attributes = array();
          $variations         = array();
          $adding_to_cart     = wc_get_product( $product_id );

          if ( ! $adding_to_cart ) {
            continue;
          }

          // If the $product_id was in fact a variation ID, update the variables.
          if ( $adding_to_cart->is_type( 'variation' ) ) {
            $variation_id   = $product_id;
            $product_id     = $adding_to_cart->get_parent_id();
            $adding_to_cart = wc_get_product( $product_id );

            if ( ! $adding_to_cart ) {
              continue;
            }
          }

          // Gather posted attributes.
          $posted_attributes = array();

          foreach ( $adding_to_cart->get_attributes() as $attribute ) {
            if ( ! $attribute['is_variation'] ) {
              continue;
            }
            $attribute_key = 'attribute_' . sanitize_title( $attribute['name'] );

            if ( isset( $_REQUEST[ $attribute_key ] ) ) {
              if ( $attribute['is_taxonomy'] ) {
                // Don't use wc_clean as it destroys sanitized characters.
                $value = sanitize_title( wp_unslash( $_REQUEST[ $attribute_key ] ) );
              } else {
                $value = html_entity_decode( wc_clean( wp_unslash( $_REQUEST[ $attribute_key ] ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); // WPCS: sanitization ok.
              }

              $posted_attributes[ $attribute_key ] = $value;
            }
          }

          // If no variation ID is set, attempt to get a variation ID from posted attributes.
          if ( empty( $variation_id ) ) {
            $data_store   = WC_Data_Store::load( 'product' );
            $variation_id = $data_store->find_matching_product_variation( $adding_to_cart, $posted_attributes );
          }

          // Do we have a variation ID?
          if ( empty( $variation_id ) ) {
            throw new Exception( __( 'Please choose product options…', 'woocommerce' ) );
          }

          // Check the data we have is valid.
          $variation_data = wc_get_product_variation_attributes( $variation_id );

          foreach ( $adding_to_cart->get_attributes() as $attribute ) {
            if ( ! $attribute['is_variation'] ) {
              continue;
            }

            // Get valid value from variation data.
            $attribute_key = 'attribute_' . sanitize_title( $attribute['name'] );
            $valid_value   = isset( $variation_data[ $attribute_key ] ) ? $variation_data[ $attribute_key ]: '';

            /**
             * If the attribute value was posted, check if it's valid.
             *
             * If no attribute was posted, only error if the variation has an 'any' attribute which requires a value.
             */
            if ( isset( $posted_attributes[ $attribute_key ] ) ) {
              $value = $posted_attributes[ $attribute_key ];

              // Allow if valid or show error.
              if ( $valid_value === $value ) {
                $variations[ $attribute_key ] = $value;
              } elseif ( '' === $valid_value && in_array( $value, $attribute->get_slugs() ) ) {
                // If valid values are empty, this is an 'any' variation so get all possible values.
                $variations[ $attribute_key ] = $value;
              } else {
                throw new Exception( sprintf( __( 'Invalid value posted for %s', 'woocommerce' ), wc_attribute_label( $attribute['name'] ) ) );
              }
            } elseif ( '' === $valid_value ) {
              $missing_attributes[] = wc_attribute_label( $attribute['name'] );
            }
          }
          if ( ! empty( $missing_attributes ) ) {
            throw new Exception( sprintf( _n( '%s is a required field', '%s are required fields', count( $missing_attributes ), 'woocommerce' ), wc_format_list_of_items( $missing_attributes ) ) );
          }

        $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity, $variation_id, $variations );

        if ( $passed_validation && false !== WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variations ) ) {
          wc_add_to_cart_message( array( $product_id => $quantity ), true );
        }
      }
  }
}
add_action( 'wp_loaded', 'woocommerce_maybe_add_multiple_products_to_cart', 15 );

Here I had forced $_REQUEST[ 'add-to-cart' ] to take the intended product id. Overwriting global variable doesn't sound good approach but it keeps DRY approach and also make all native function available to user.

add_action( 'wp_loaded', 'add_multiple_to_cart_action', 20 );

function add_multiple_to_cart_action() {
    if ( ! isset( $_REQUEST['multiple-item-to-cart'] ) || false === strpos( wp_unslash( $_REQUEST['multiple-item-to-cart'] ), '|' ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
            return;
        }

    wc_nocache_headers();

    $product_ids        = apply_filters( 'woocommerce_add_to_cart_product_id', wp_unslash( $_REQUEST['multiple-item-to-cart'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
    $product_ids = explode( '|', $product_ids );
    if( ! is_array( $product_ids ) ) return;

    $product_ids = array_map( 'absint', $product_ids );
    $was_added_to_cart = false;
    $last_product_id = end($product_ids);
    //stop re-direction
    add_filter( 'woocommerce_add_to_cart_redirect', '__return_false' );
    foreach ($product_ids as $index => $product_id ) {
        $product_id = absint(  $product_id  );
        if( empty( $product_id ) ) continue;
        $_REQUEST['add-to-cart'] = $product_id;
        if( $product_id === $last_product_id ) {

            add_filter( 'option_woocommerce_cart_redirect_after_add', function() { 
                return 'yes'; 
            } );
        } else {
            add_filter( 'option_woocommerce_cart_redirect_after_add', function() { 
                return 'no'; 
            } );
        }

        WC_Form_Handler::add_to_cart_action();
    }
}

Example:

https://your-domain/cart?multiple-item-to-cart=68|69 Thanks

Same answer as others, with support for multiple quantities.

Example url: http://store.amitbend.com/cart/?add-to-cart=188,187,189&quantities=3,2,1


function woocommerce_maybe_add_multiple_products_to_cart() {
// Make sure WC is installed, and add-to-cart qauery arg exists, and contains at least one comma.
if ( ! class_exists( 'WC_Form_Handler' ) || empty( $_REQUEST['add-to-cart'] ) || false === strpos( $_REQUEST['add-to-cart'], ',' ) ) {
    return;
}

// Remove WooCommerce's hook, as it's useless (doesn't handle multiple products).
remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 );

$product_ids = explode( ',', $_REQUEST['add-to-cart'] );
$quantities = explode( ',', $_REQUEST['quantities'] );

$count       = count( $product_ids );
$number      = 0;

foreach ( $product_ids as $product_id ) {
    if ( ++$number === $count ) {
        // Ok, final item, let's send it back to woocommerce's add_to_cart_action method for handling.
        $_REQUEST['add-to-cart'] = $product_id;

        return WC_Form_Handler::add_to_cart_action();
    }

    $product_id        = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $product_id ) );
    $was_added_to_cart = false;
    $adding_to_cart    = wc_get_product( $product_id );

    if ( ! $adding_to_cart ) {
        continue;
    }

    $add_to_cart_handler = apply_filters( 'woocommerce_add_to_cart_handler', $adding_to_cart->product_type, $adding_to_cart );

    /*
     * Sorry.. if you want non-simple products, you're on your own.
     *
     * Related: WooCommerce has set the following methods as private:
     * WC_Form_Handler::add_to_cart_handler_variable(),
     * WC_Form_Handler::add_to_cart_handler_grouped(),
     * WC_Form_Handler::add_to_cart_handler_simple()
     *
     * Why you gotta be like that WooCommerce?
     */
    if ( 'simple' !== $add_to_cart_handler ) {
        continue;
    }
//         $_REQUEST['quantity'] = ! empty( $id_and_quantity[1] ) ? absint( $id_and_quantity[1] ) : 1;
$_REQUEST['quantity'] = ! empty( $quantities[$number] ) ? absint( $quantities[$number] ) : 1;
    $quantity          = empty( $quantities[$number - 1] ) ? 1 : wc_stock_amount(  $quantities[$number - 1] );
//     $quantity          = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( $_REQUEST['quantity'] );
    $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );

    if ( $passed_validation && false !== WC()->cart->add_to_cart( $product_id, $quantity ) ) {
        wc_add_to_cart_message( array( $product_id => $quantity ), true );
    }
}
}

 // Fire before the WC_Form_Handler::add_to_cart_action callback.
 add_action( 'wp_loaded',        'woocommerce_maybe_add_multiple_products_to_cart', 15 );
// remove "added to cart" notice
add_filter( 'wc_add_to_cart_message_html', '__return_false' );

The correct syntax is

add-to-cart=product1id:quantity,product2id:quantity  

This is the code https://www.webroomtech.com/woocommerce-add-multiple-products-to-cart-via-url/

They don't show this syntax for quantities on the tutorial, I found it looking at the code.

If you don't want to code anything, you can create a grouped product with all the products you want to add to the cart added as Linked Products.

Then the url will be as follow:

https://url.com/shop/cart/?add-to-cart=3001&quantity[2002]=1&quantity[1001]=1
  • 3001 = Grouped Product id
  • 2002 = Linked Product1 id
  • 1001 = Linked Product2 id

Don't forget to specify quantities.

Also, you can change the catalog visibility to "hidden" so that grouped product doesn't appear in your store.

I took a different approach to this. Instead of killing the WC_Form_Handler, I use it! I have it run for each product. This seems simpler to me.

You can use this alone, or also with the regular add-to-cart.

http://example.com?add-more-to-cart=1000,10001,10002

http://example.com?add-to-cart=1000&add-more-to-cart=10001,10002

class add_more_to_cart {

    private $prevent_redirect = false; //used to prevent WC from redirecting if we have more to process

    function __construct() {
        if ( ! isset( $_REQUEST[ 'add-more-to-cart' ] ) ) return; //don't load if we don't have to
        $this->prevent_redirect = 'no'; //prevent WC from redirecting so we can process additional items
        add_action( 'wp_loaded', [ $this, 'add_more_to_cart' ], 21 ); //fire after WC does, so we just process extra ones
        add_action( 'pre_option_woocommerce_cart_redirect_after_add', [ $this, 'intercept_option' ], 9000 ); //intercept the WC option to force no redirect
    }

    function intercept_option() {
        return $this->prevent_redirect;
    }

    function add_more_to_cart() {
        $product_ids = explode( ',', $_REQUEST['add-more-to-cart'] );
        $count       = count( $product_ids );
        $number      = 0;

        foreach ( $product_ids as $product_id ) {
            if ( ++$number === $count ) $this->prevent_redirect = false; //this is the last one, so let WC redirect if it wants to.
            $_REQUEST['add-to-cart'] = $product_id; //set the next product id
            WC_Form_Handler::add_to_cart_action(); //let WC run its own code
        }
    }
}
new add_more_to_cart;

WooCommerce 4.0, an easier way to do this is to use the template_redirect hook which fires early off in the process. In theory you could decode a URL and add multiple items to cart or POST a form and process the POST. The simplest form is:

add_action( 'template_redirect', function() {
    
    if( ! isset( $_POST['products'] ) ) {
        return;
    }
    
    $products = array_filter( $_POST['products'] );
    
    foreach( $products as $product_id => $quantity ) {
        WC()->cart->add_to_cart( $product_id, $quantity );
    }
    
} );

support variations and quantities using add-to-cart and quantities

// Make sure WC is installed, and add-to-cart qauery arg exists, and contains at least one comma.
if ( ! class_exists( 'WC_Form_Handler' ) || empty( $_REQUEST['add-to-cart'] ) || false === strpos( $_REQUEST['add-to-cart'], ',' ) ) {
    return;
}

remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 );

$product_ids = explode( ',', $_REQUEST['add-to-cart'] );
$quantities = explode( ',', $_REQUEST['quantities'] );
$count       = count( $product_ids );
$number      = 0;

foreach ( $product_ids as $product_id ) {
    if ( ++$number === $count ) {
        // Ok, final item, let's send it back to woocommerce's add_to_cart_action method for handling.
        $_REQUEST['add-to-cart'] = $product_id;

        return WC_Form_Handler::add_to_cart_action();
    }

    $product_id        = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $product_id ) );
    $was_added_to_cart = false;

    $adding_to_cart    = wc_get_product( $product_id );

    if ( ! $adding_to_cart ) {
        continue;
    }

    if ( $adding_to_cart->is_type( 'simple' ) ) {
        $_REQUEST['quantity'] = ! empty( $quantities[$number] ) ? absint( $quantities[$number] ) : 1;
        $quantity          = empty( $quantities[$number - 1] ) ? 1 : wc_stock_amount(  $quantities[$number - 1] );
        // quantity applies to all products atm
        //$quantity          = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( $_REQUEST['quantity'] );
        $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );

        if ( $passed_validation && false !== WC()->cart->add_to_cart( $product_id, $quantity ) ) {
            wc_add_to_cart_message( array( $product_id => $quantity ), true );
        }

    } else {

        $variation_id       = empty( $_REQUEST['variation_id'] ) ? '' : absint( wp_unslash( $_REQUEST['variation_id'] ) );
        $quantity           = empty( $quantities[$number - 1] ) ? 1 : wc_stock_amount( wp_unslash( $quantities[$number - 1] ) ); // WPCS: sanitization ok.
        $missing_attributes = array();
        $variations         = array();
        $adding_to_cart     = wc_get_product( $product_id );

        if ( ! $adding_to_cart ) {
          continue;
        }

        // If the $product_id was in fact a variation ID, update the variables.
        if ( $adding_to_cart->is_type( 'variation' ) ) {
          $variation_id   = $product_id;
          $product_id     = $adding_to_cart->get_parent_id();
          $adding_to_cart = wc_get_product( $product_id );

          if ( ! $adding_to_cart ) {
            continue;
          }
        }

        // Gather posted attributes.
        $posted_attributes = array();

        foreach ( $adding_to_cart->get_attributes() as $attribute ) {
          if ( ! $attribute['is_variation'] ) {
            continue;
          }
          $attribute_key = 'attribute_' . sanitize_title( $attribute['name'] );

          if ( isset( $_REQUEST[ $attribute_key ] ) ) {
            if ( $attribute['is_taxonomy'] ) {
              // Don't use wc_clean as it destroys sanitized characters.
              $value = sanitize_title( wp_unslash( $_REQUEST[ $attribute_key ] ) );
            } else {
              $value = html_entity_decode( wc_clean( wp_unslash( $_REQUEST[ $attribute_key ] ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); // WPCS: sanitization ok.
            }

            $posted_attributes[ $attribute_key ] = $value;
          }
        }

        // If no variation ID is set, attempt to get a variation ID from posted attributes.
        if ( empty( $variation_id ) ) {
          $data_store   = WC_Data_Store::load( 'product' );
          $variation_id = $data_store->find_matching_product_variation( $adding_to_cart, $posted_attributes );
        }

        // Do we have a variation ID?
        if ( empty( $variation_id ) ) {
          throw new Exception( __( 'Please choose product options…', 'woocommerce' ) );
        }

        // Check the data we have is valid.
        $variation_data = wc_get_product_variation_attributes( $variation_id );

        foreach ( $adding_to_cart->get_attributes() as $attribute ) {
          if ( ! $attribute['is_variation'] ) {
            continue;
          }

          // Get valid value from variation data.
          $attribute_key = 'attribute_' . sanitize_title( $attribute['name'] );
          $valid_value   = isset( $variation_data[ $attribute_key ] ) ? $variation_data[ $attribute_key ]: '';

          /**
           * If the attribute value was posted, check if it's valid.
           *
           * If no attribute was posted, only error if the variation has an 'any' attribute which requires a value.
           */
          if ( isset( $posted_attributes[ $attribute_key ] ) ) {
            $value = $posted_attributes[ $attribute_key ];

            // Allow if valid or show error.
            if ( $valid_value === $value ) {
              $variations[ $attribute_key ] = $value;
            } elseif ( '' === $valid_value && in_array( $value, $attribute->get_slugs() ) ) {
              // If valid values are empty, this is an 'any' variation so get all possible values.
              $variations[ $attribute_key ] = $value;
            } else {
              throw new Exception( sprintf( __( 'Invalid value posted for %s', 'woocommerce' ), wc_attribute_label( $attribute['name'] ) ) );
            }
          } elseif ( '' === $valid_value ) {
            $missing_attributes[] = wc_attribute_label( $attribute['name'] );
          }
        }
        if ( ! empty( $missing_attributes ) ) {
          throw new Exception( sprintf( _n( '%s is a required field', '%s are required fields', count( $missing_attributes ), 'woocommerce' ), wc_format_list_of_items( $missing_attributes ) ) );
        }

      $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity, $variation_id, $variations );

      if ( $passed_validation && false !== WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variations ) ) {
        wc_add_to_cart_message( array( $product_id => $quantity ), true );
      }
    }
}

}

I've tried these solutions but nothing worked since init ran a few times and the products were adding a few times as well so the quantities were off.
In addition, I wanted to have the ability to add a coupon from the URL as well...

So I've written my own function that takes care of that, I hope it helps someone. Here's the code:

/*
 * Init function
 * 1. Apply coupon code from URL
 * 2. Add to cart: Multiple products add via URL
 */
function my_template_redirect() {
    if( !is_cart() ) {
        return;
    }
    
    if( isset( WC()->session ) && !WC()->session->has_session() ) {
        WC()->session->set_customer_session_cookie( true );
    }
    
    if( isset( $_GET['coupon_code'] ) && empty( WC()->session->get( 'added_coupon_code' ) ) ) {
        $coupon_code = esc_attr( $_GET['coupon_code'] );
        
        if( !empty( $coupon_code ) && !WC()->cart->has_discount( $coupon_code ) ) {
            WC()->cart->add_discount( $coupon_code );
            
            WC()->session->set( 'added_coupon_code', true );
        }
    }
    
    if( empty( WC()->session->get( 'added_products_to_cart' ) ) ) {
        $product_ids = array();
        $quantities  = array();
        
        if( isset( $_GET['add-to-cart'] ) ) {
            if( false !== strpos( $_GET['add-to-cart'], ',' ) ) {
                $product_ids = explode( ',', $_GET['add-to-cart'] );
            }
        }
        
        if( isset( $_GET['quantity'] ) ) {
            if( false !== strpos( $_GET['quantity'], ',' ) ) {
                $quantities = explode( ',', $_GET['quantity'] );
            }
        }
        
        if( !empty( $product_ids ) ) {
            $products = array();
            
            for( $i = 0; $i < count( $product_ids ); $i++ ) {
                if( isset( $product_ids[ $i ] ) ) {
                    $products[ $product_ids[ $i ] ] = isset( $quantities[ $i ] ) ? $quantities[ $i ] : 1;
                }
            }
            
            if( !empty( $products ) ) {
                foreach( $products as $key => $value ) {
                    WC()->cart->add_to_cart( $key, $value );
                    
                    WC()->session->set( 'added_products_to_cart', true );
                }
            }
        }
    }
}
add_action( 'template_redirect', 'my_template_redirect' );

/*
 * Clear session variables on thank you page.
 */
function my_woocommerce_thankyou( $order_id ) {
    WC()->session->__unset( 'added_coupon_code' );
    WC()->session->__unset( 'added_products_to_cart' );
}
add_action( 'woocommerce_thankyou', 'my_woocommerce_thankyou' );

Example usage:
https://example.com/cart/?add-to-cart=19737,19713&quantity=2,1&coupon_code=TEST

A few notes:

  • This works with or without quantity and coupon code parameters, if you choose to omit them the quantity of the products that will be added to the cart will be 1.
  • The product ids have to be separated using commas without spaces.
  • Match the product ids with the quantity in the correct order, in this example 2 units of product 19737 will be added to the cart.
  • This solution works only for URLs that send the user to the cart page.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM