Skip to main content

¿Haz intentado alguna vez agregar varios productos al carrito a la vez?

Te habrás dado cuenta que solo puedes agregar un producto a la vez, WordPress y WooCommerce no tienen esa funcionalidad, ¡No te preocupes! mediante código se puede solucionar.

Simplemente hay que agregar una función en el archivo functions.php de tu wordpress, pero espera no vallas tan rápido, te recomiendo hacerlo en tu tema hijo (child theme), de esta forma no perderás esta modificación si actualizas tu wordpress o tu tema.

Basta de cháchara, vamos al lio…

Opción 1

Esta opción te permite añadir al carrito varios productos a la par de asignarle cantidades, …Maravilloso ¿No?, la url se crea así: “dominio.com/nombredelacesta/?add-to-cart=id1,id2,id3&quantities=3,2,1” os dejo un ejemplo para que puedas verlo de forma más clara.

https://veradesign.es/carrito/?add-to-cart=1265,5869,4546,7478&quantities=2,3,1,5

Si no deseas utilizar cantidades o no las necesitas omite &quantities=X,X,X

/* Función para agregar varios productos a la vez por url */
function woocommerce_maybe_add_multiple_products_to_cart() {
// Asegúrate que WooCommerce está instalado, el parametro query add-to-cart existe y contiene al menos una coma.
if ( ! class_exists( 'WC_Form_Handler' ) || empty( $_REQUEST['add-to-cart'] ) || false === strpos( $_REQUEST['add-to-cart'], ',' ) ) {
    return;
}

// Eliminar el hook de WooCommerce, ya que es inútil (no maneja múltiples productos).
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, último punto, enviémoslo de nuevo al método add_to_cart_action de woocommerce para su manejo.
        $_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 );

    /*
     * Lo siento... si quieres productos no simples, utiliza la segunda versión de este código.
     *
     * Relacionado: WooCommerce ha establecido los siguientes métodos como privados:
     * WC_Form_Handler::add_to_cart_handler_variable(),
     * WC_Form_Handler::add_to_cart_handler_grouped(),
     * WC_Form_Handler::add_to_cart_handler_simple()
     *
     * ¿Por qué tienes que ser así 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 );
    }
}
}

 // Se dispara antes de la llamada de retorno de WC_Form_Handler::add_to_cart_action.
 add_action( 'wp_loaded',        'woocommerce_maybe_add_multiple_products_to_cart', 15 );
// eliminar el aviso de "añadido a la cesta".
add_filter( 'wc_add_to_cart_message_html', '__return_false' );

Al probarlo por primera vez mostraba continuamente el aviso de “Producto añadido al carrito”, molestaba un montón, así que investigue como eliminarlo, y lo he agregado, de esta forma al añadir varios productos a la vez no se muestra el aviso, no te preocupes si agregas uno solo si muestra el aviso.

Opción 2: Productos Variables y Cantidades

Esta opción permite añadir al carrito varios productos variables y sus respectivas cantidades.

La url se crea de la misma forma que la anterior, realmente fácil.

// Asegúrate que WooCommerce está instalado, el parametro query add-to-cart existe y contiene al menos una coma.
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, último punto, enviémoslo de nuevo al método add_to_cart_action de woocommerce para su procesamiento.
        $_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] );
        // la cantidad se aplica a todos los productos 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;
        }

        // Si el $product_id era de hecho un ID de variables, actualiza las 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;
          }
        }

        // Recoge los atributos contabilizados.
        $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;
          }
        }

        // No utilizar wc_clean ya que destruye los caracteres limpios.
        if ( empty( $variation_id ) ) {
          $data_store   = WC_Data_Store::load( 'product' );
          $variation_id = $data_store->find_matching_product_variation( $adding_to_cart, $posted_attributes );
        }

        // ¿Tenemos una ID de variable?
        if ( empty( $variation_id ) ) {
          throw new Exception( __( 'Please choose product options…', 'woocommerce' ) );
        }

        // Comprueba que los datos que tenemos son válidos.
        $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 ]: '';

          /**
          * Si el valor del atributo fue publicado, comprueba si es válido.
          *
          * Si no se contabilizó ningún atributo, sólo error si la variación tiene un atributo 'any' que requiere un valor.
           */
          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() ) ) {
              // Si los valores válidos están vacíos, intentará de una variación "cualquiera" para obtener todos los valores posibles.
              $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 );
      }
    }
}

Están dos opciones están probadas por mi en un WordPress versión 5.7.2 con WooCommerce 5.4.1, si tienes alguna duda o problema déjalo en los comentarios.

Espero sea de ayuda!!!

Carlos Vera

Carlos Vera

Asesor de Marketing y Diseñador Web Profesional

Dejar un comentario