WC_Cart::add_to_cart() │ public │ WC 1.0
Add a product to the cart.
Method of the class: WC_Cart{}
Hooks from the method
Return
String|true|false
. $cart_item_key
Usage
$WC_Cart = new WC_Cart(); $WC_Cart->add_to_cart( $product_id, $quantity, $variation_id, $variation, $cart_item_data );
- $product_id(int)
- contains the id of the product to add to the cart.
- $quantity(int)
- contains the quantity of the item to add.
Default: 1 - $variation_id(int)
- ID of the variation being added to the cart.
- $variation(array)
- attribute values.
Default: array() - $cart_item_data(array)
- extra cart item data we want to pass into the item.
Default: array()
WC_Cart::add_to_cart() WC Cart::add to cart code WC 9.4.2
public function add_to_cart( $product_id = 0, $quantity = 1, $variation_id = 0, $variation = array(), $cart_item_data = array() ) { try { $product_id = absint( $product_id ); $variation_id = absint( $variation_id ); // Ensure we don't add a variation to the cart directly by variation ID. if ( 'product_variation' === get_post_type( $product_id ) ) { $variation_id = $product_id; $product_id = wp_get_post_parent_id( $variation_id ); } $product_data = wc_get_product( $variation_id ? $variation_id : $product_id ); $quantity = apply_filters( 'woocommerce_add_to_cart_quantity', $quantity, $product_id ); if ( $quantity <= 0 || ! $product_data || 'trash' === $product_data->get_status() ) { return false; } if ( $product_data->is_type( 'variation' ) ) { $missing_attributes = array(); $parent_data = wc_get_product( $product_data->get_parent_id() ); $variation_attributes = $product_data->get_variation_attributes(); // Filter out 'any' variations, which are empty, as they need to be explicitly specified while adding to cart. $variation_attributes = array_filter( $variation_attributes ); // Gather posted attributes. $posted_attributes = array(); foreach ( $parent_data->get_attributes() as $attribute ) { if ( ! $attribute['is_variation'] ) { continue; } $attribute_key = 'attribute_' . sanitize_title( $attribute['name'] ); if ( isset( $variation[ $attribute_key ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( $attribute['is_taxonomy'] ) { // Don't use wc_clean as it destroys sanitized characters. $value = sanitize_title( wp_unslash( $variation[ $attribute_key ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended } else { $value = html_entity_decode( wc_clean( wp_unslash( $variation[ $attribute_key ] ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended } // Don't include if it's empty. if ( ! empty( $value ) || '0' === $value ) { $posted_attributes[ $attribute_key ] = $value; } } } // Merge variation attributes and posted attributes. $posted_and_variation_attributes = array_merge( $variation_attributes, $posted_attributes ); // 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( $parent_data, $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 ); $attributes = array(); foreach ( $parent_data->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_and_variation_attributes[ $attribute_key ] ) ) { $value = $posted_and_variation_attributes[ $attribute_key ]; // Allow if valid or show error. if ( $valid_value === $value ) { $attributes[ $attribute_key ] = $value; } elseif ( '' === $valid_value && in_array( $value, $attribute->get_slugs(), true ) ) { // If valid values are empty, this is an 'any' variation so get all possible values. $attributes[ $attribute_key ] = $value; } else { /* translators: %s: Attribute name. */ 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'] ); } $variation = $attributes; } if ( ! empty( $missing_attributes ) ) { /* translators: %s: Attribute name. */ 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 ) ) ); } } // Validate variation ID. if ( 0 < $variation_id && // Only check if there's any variation_id. ( ! $product_data->is_type( 'variation' ) || // Check if isn't a variation, it suppose to be a variation at this point. $product_data->get_parent_id() !== $product_id // Check if belongs to the selected variable product. ) ) { $product = wc_get_product( $product_id ); /* translators: 1: product link, 2: product name */ throw new Exception( sprintf( __( 'The selected product isn\'t a variation of %2$s, please choose product options by visiting <a href="%1$s" title="%2$s">%2$s</a>.', 'woocommerce' ), esc_url( $product->get_permalink() ), esc_html( $product->get_name() ) ) ); } // Load cart item data - may be added by other plugins. $cart_item_data = (array) apply_filters( 'woocommerce_add_cart_item_data', $cart_item_data, $product_id, $variation_id, $quantity ); // Generate a ID based on product ID, variation ID, variation data, and other cart item data. $cart_id = $this->generate_cart_id( $product_id, $variation_id, $variation, $cart_item_data ); // Find the cart item key in the existing cart. $cart_item_key = $this->find_product_in_cart( $cart_id ); // Force quantity to 1 if sold individually and check for existing item in cart. if ( $product_data->is_sold_individually() ) { $quantity = apply_filters( 'woocommerce_add_to_cart_sold_individually_quantity', 1, $quantity, $product_id, $variation_id, $cart_item_data ); $found_in_cart = apply_filters( 'woocommerce_add_to_cart_sold_individually_found_in_cart', $cart_item_key && $this->cart_contents[ $cart_item_key ]['quantity'] > 0, $product_id, $variation_id, $cart_item_data, $cart_id ); if ( $found_in_cart ) { /* translators: %s: product name */ $message = sprintf( __( 'You cannot add another "%s" to your cart.', 'woocommerce' ), $product_data->get_name() ); /** * Filters message about more than 1 product being added to cart. * * @since 4.5.0 * @param string $message Message. * @param WC_Product $product_data Product data. */ $message = apply_filters( 'woocommerce_cart_product_cannot_add_another_message', $message, $product_data ); $wp_button_class = wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : ''; throw new Exception( sprintf( '%s <a href="%s" class="button wc-forward%s">%s</a>', $message, wc_get_cart_url(), esc_attr( $wp_button_class ), __( 'View cart', 'woocommerce' ) ) ); } } if ( ! $product_data->is_purchasable() ) { $message = __( 'Sorry, this product cannot be purchased.', 'woocommerce' ); /** * Filters message about product unable to be purchased. * * @since 3.8.0 * @param string $message Message. * @param WC_Product $product_data Product data. */ $message = apply_filters( 'woocommerce_cart_product_cannot_be_purchased_message', $message, $product_data ); throw new Exception( $message ); } // Stock check - only check if we're managing stock and backorders are not allowed. if ( ! $product_data->is_in_stock() ) { /* translators: %s: product name */ $message = sprintf( __( 'You cannot add "%s" to the cart because the product is out of stock.', 'woocommerce' ), $product_data->get_name() ); /** * Filters message about product being out of stock. * * @since 4.5.0 * @param string $message Message. * @param WC_Product $product_data Product data. */ $message = apply_filters( 'woocommerce_cart_product_out_of_stock_message', $message, $product_data ); throw new Exception( $message ); } if ( ! $product_data->has_enough_stock( $quantity ) ) { $stock_quantity = $product_data->get_stock_quantity(); /* translators: 1: product name 2: quantity in stock */ $message = sprintf( __( 'You cannot add that amount of "%1$s" to the cart because there is not enough stock (%2$s remaining).', 'woocommerce' ), $product_data->get_name(), wc_format_stock_quantity_for_display( $stock_quantity, $product_data ) ); /** * Filters message about product not having enough stock. * * @since 4.5.0 * @param string $message Message. * @param WC_Product $product_data Product data. * @param int $stock_quantity Quantity remaining. */ $message = apply_filters( 'woocommerce_cart_product_not_enough_stock_message', $message, $product_data, $stock_quantity ); throw new Exception( $message ); } // Stock check - this time accounting for whats already in-cart. if ( $product_data->managing_stock() ) { $products_qty_in_cart = $this->get_cart_item_quantities(); if ( isset( $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ] ) && ! $product_data->has_enough_stock( $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ] + $quantity ) ) { $stock_quantity = $product_data->get_stock_quantity(); $stock_quantity_in_cart = $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ]; $wp_button_class = wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : ''; $message = sprintf( '%s <a href="%s" class="button wc-forward%s">%s</a>', /* translators: 1: quantity in stock 2: current quantity */ sprintf( __( 'You cannot add that amount to the cart — we have %1$s in stock and you already have %2$s in your cart.', 'woocommerce' ), wc_format_stock_quantity_for_display( $stock_quantity, $product_data ), wc_format_stock_quantity_for_display( $stock_quantity_in_cart, $product_data ) ), wc_get_cart_url(), esc_attr( $wp_button_class ), __( 'View cart', 'woocommerce' ) ); /** * Filters message about product not having enough stock accounting for what's already in the cart. * * @param string $message Message. * @param WC_Product $product_data Product data. * @param int $stock_quantity Quantity remaining. * @param int $stock_quantity_in_cart * * @since 5.3.0 */ $message = apply_filters( 'woocommerce_cart_product_not_enough_stock_already_in_cart_message', $message, $product_data, $stock_quantity, $stock_quantity_in_cart ); throw new Exception( $message ); } } // If cart_item_key is set, the item is already in the cart. if ( $cart_item_key ) { $new_quantity = $quantity + $this->cart_contents[ $cart_item_key ]['quantity']; $this->set_quantity( $cart_item_key, $new_quantity, false ); } else { $cart_item_key = $cart_id; // Add item after merging with $cart_item_data - hook to allow plugins to modify cart item. $this->cart_contents[ $cart_item_key ] = apply_filters( 'woocommerce_add_cart_item', array_merge( $cart_item_data, array( 'key' => $cart_item_key, 'product_id' => $product_id, 'variation_id' => $variation_id, 'variation' => $variation, 'quantity' => $quantity, 'data' => $product_data, 'data_hash' => wc_get_cart_item_data_hash( $product_data ), ) ), $cart_item_key ); } $this->cart_contents = apply_filters( 'woocommerce_cart_contents_changed', $this->cart_contents ); do_action( 'woocommerce_add_to_cart', $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ); return $cart_item_key; } catch ( Exception $e ) { if ( $e->getMessage() ) { wc_add_notice( $e->getMessage(), 'error' ); } return false; } }