【问题标题】:Adding multiple items to WooCommerce cart at once一次将多个项目添加到 WooCommerce 购物车
【发布时间】:2017-07-23 02:20:16
【问题描述】:

我有 3 个不同商品的 ID,要添加到我的购物车。 我可以使用https://url.com/shop/cart/?add-to-cart=3001,但是当我想添加 3 个项目时,我做不到。我可以添加任何功能/脚本来将此功能添加到我的购物网站吗?

我尝试在add-to-cart 之后添加一个& 并尝试添加一个新值,但 GET 会被覆盖,对吗?: https://url.com/shop/cart/?add-to-cart=3001&add-to-cart=2002&add-to-cart=1001

【问题讨论】:

    标签: php woocommerce


    【解决方案1】:

    我找到了答案!

    只需将以下脚本添加到主题的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 );
    

    然后您可以简单地使用http://shop.com/shop/cart/?add-to-cart=3001,3282 一次添加多个项目。在不同的 ID 之间加逗号。

    感谢dsgnwrks 的解决方案。

    【讨论】:

    • @Hokascha 我更新/修复了该功能并将其发布在下面
    【解决方案2】:

    以防其他人像我一样通过寻找此功能来。我更新了顶部评论的代码,使其可以与 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 );
    

    【讨论】:

      【解决方案3】:

      感谢@thatgerhard 和dsgnwrks
      我找到了支持变化的解决方案:

      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 );
      

      【讨论】:

      • 它看起来不支持多种变体,对吧?只有 1 个变体
      • 不,它支持多种变体。
      • 这对我很有用!谢谢@AliNasr!您是否有任何建议的添加/修改以使您的 sn-p 允许在 URL 中简单地包含每个产品变体的数量?
      【解决方案4】:

      在这里我强制$_REQUEST[ 'add-to-cart' ] 获取预期的产品ID。覆盖全局变量听起来不是好方法,但它保留了 DRY 方法,并使所有本机函数都可供用户使用。

      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();
          }
      }
      

      例子:

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

      【讨论】:

        【解决方案5】:

        与其他答案相同,支持多个数量。

        示例网址: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' );
        
        

        【讨论】:

        【解决方案6】:

        正确的语法是

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

        这是代码 https://www.webroomtech.com/woocommerce-add-multiple-products-to-cart-via-url/

        他们没有在教程中显示这种数量的语法,我是在查看代码时发现的。

        【讨论】:

          【解决方案7】:

          WooCommerce 4.0,一个更简单的方法是使用template_redirect 钩子,它会在这个过程的早期触发。理论上,您可以解码 URL 并将多个项目添加到购物车或发布表单并处理 POST。最简单的形式是:

          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 );
              }
              
          } );
          

          【讨论】:

          • 我需要它来支持最新的 woocommerce 版本吗?这是 5.3.0 .. 不工作
          • 这在 5.3.0 中同样有效。您发布的数据可能与我的不同,但如果您将产品 ID 和数量传递给add_to_cart() 方法,如上所示,它会按预期工作。
          【解决方案8】:

          如果您不想编写任何代码,您可以创建一个分组产品,将您想要添加到购物车的所有产品添加为链接产品。

          那么url如下:

          https://url.com/shop/cart/?add-to-cart=3001&quantity[2002]=1&quantity[1001]=1
          
          • 3001 = 分组产品 ID
          • 2002 = 链接产品 1 id
          • 1001 = 链接产品 2 id

          不要忘记指定数量。

          此外,您可以将目录可见性更改为“隐藏”,这样分组的产品就不会出现在您的商店中。

          【讨论】:

            【解决方案9】:

            我对此采取了不同的方法。我没有杀死 WC_Form_Handler,而是使用它!我为每个产品运行它。这对我来说似乎更简单。

            您可以单独使用它,也可以与常规添加到购物车一起使用。

            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;
            

            【讨论】:

            • 如果你还想使用 WC_Form_Handler::add_to_cart_action();您可以执行add-more-to-cart=1000,10001|5,10002|10 之类的操作,然后对其进行解析并按数量运行 add_to_cart_action()。
            【解决方案10】:

            使用添加到购物车和数量来支持变化和数量

            // 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 );
                  }
                }
            }
            

            }

            【讨论】:

            • 欢迎来到 Stack Overflow!虽然您的回答可能会解决问题,但 including an explanation 关于如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。您可以编辑您的答案以添加解释并指出适用的限制和假设。 - From Review
            【解决方案11】:

            我已经尝试了这些解决方案,但没有任何效果,因为 init 运行了几次并且产品也添加了几次,所以数量减少了。
            此外,我还希望能够从 URL 添加优惠券...

            所以我编写了自己的函数来处理这个问题,我希望它对某人有所帮助。代码如下:

            /*
             * 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' );
            

            用法示例:
            https://example.com/cart/?add-to-cart=19737,19713&quantity=2,1&coupon_code=TEST

            一些注意事项:

            • 无论有无数量和优惠券代码参数均可使用,如果您选择省略它们,将添加到购物车的产品数量将为 1。
            • 产品 ID 必须使用不带空格的逗号分隔。
            • 将产品 ID 与正确订单中的数量相匹配,在此示例中,将向购物车添加 2 件产品 19737。
            • 此解决方案仅适用于将用户引导至购物车页面的 URL。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-10-10
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-01-21
              相关资源
              最近更新 更多