If you’re not familiar, WooCommerce offers a way to link to the checkout/cart page and automatically add a product to the cart (h/t Justin). You can create a link like so:
$product_id = 55; $url = esc_url_raw( add_query_arg( 'add-to-cart', $product_id, wc_get_checkout_url() ) );
I recently (somewhat annoyingly) discovered that while that works fairly well, there was no way to do this for multiple products. So I’ve created a snippet that will allow you to do so by adding a comma-separated list of products ids:
function woocommerce_maybe_add_multiple_products_to_cart( $url = false ) { // 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 $id_and_quantity ) { // Check for quantities defined in curie notation (<product_id>:<product_quantity>) // https://dsgnwrks.pro/snippets/woocommerce-allow-adding-multiple-products-to-the-cart-via-the-add-to-cart-query-string/#comment-12236 $id_and_quantity = explode( ':', $id_and_quantity ); $product_id = $id_and_quantity[0]; $_REQUEST['quantity'] = ! empty( $id_and_quantity[1] ) ? absint( $id_and_quantity[1] ) : 1; 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( $url ); } $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->get_type(), $adding_to_cart ); // Variable product handling if ( 'variable' === $add_to_cart_handler ) { woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_variable', $product_id ); // Grouped Products } elseif ( 'grouped' === $add_to_cart_handler ) { woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_grouped', $product_id ); // Custom Handler } elseif ( has_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler ) ){ do_action( 'woocommerce_add_to_cart_handler_' . $add_to_cart_handler, $url ); // Simple Products } else { woo_hack_invoke_private_method( 'WC_Form_Handler', 'add_to_cart_handler_simple', $product_id ); } } } // Fire before the WC_Form_Handler::add_to_cart_action callback. add_action( 'wp_loaded', 'woocommerce_maybe_add_multiple_products_to_cart', 15 ); /** * Invoke class private method * * @since 0.1.0 * * @param string $class_name * @param string $methodName * * @return mixed */ function woo_hack_invoke_private_method( $class_name, $methodName ) { if ( version_compare( phpversion(), '5.3', '<' ) ) { throw new Exception( 'PHP version does not support ReflectionClass::setAccessible()', __LINE__ ); } $args = func_get_args(); unset( $args[0], $args[1] ); $reflection = new ReflectionClass( $class_name ); $method = $reflection->getMethod( $methodName ); $method->setAccessible( true ); $args = array_merge( array( $class_name ), $args ); return call_user_func_array( array( $method, 'invoke' ), $args ); }
Now you can add items to the cart via the following URLs:
// Multiple products, multiple quantities per product. $product_ids = '63833:2,221916:4'; $add_to_cart_url = esc_url_raw( add_query_arg( 'add-to-cart', $product_ids, wc_get_checkout_url() ) ); // Multiple products (default quantity of 1) $product_ids = '63833,221916'; $add_to_cart_url = esc_url_raw( add_query_arg( 'add-to-cart', $product_ids, wc_get_checkout_url() ) ); // Normal add-to-cart URL $product_ids = '63833'; $add_to_cart_url = esc_url_raw( add_query_arg( 'add-to-cart', $product_ids, wc_get_checkout_url() ) );
UPDATE 04-21-17: I have updated the snippet to work with non-simple product types. (See the
MARKDOWN_HASHd8969cc70401fc7e3d75a74096dbd31dMARKDOWN_HASH
function). As indicated by the function name, this is a hack to get access to WooCommerce protected/private methods. Your milage may vary when using this snippet.
UPDATE 07-08-17: Thanks to Peder in the comments, I have updated the snippet to allow specifying different quantities per-product.