WC_Product_Data_Store_CPT::update_product_stock( int $product_id_with_stock, int|float|null $stock_quantity = null, string $operation = 'set' )

Update a product’s stock amount directly.


Description Description

Uses queries rather than update_post_meta so we can do this in one query (to avoid stock issues). Ignores manage stock setting on the product and sets quantities directly in the db: post meta and lookup tables. Uses locking to update the quantity. If the lock is not acquired, change is lost.


Parameters Parameters

$product_id_with_stock

(Required) Product ID.

$stock_quantity

(Optional) Stock quantity.

Default value: null

$operation

(Optional) Set, increase and decrease.

Default value: 'set'


Top ↑

Return Return

(int|float) New stock level.


Top ↑

Source Source

File: includes/data-stores/class-wc-product-data-store-cpt.php

	public function update_product_stock( $product_id_with_stock, $stock_quantity = null, $operation = 'set' ) {
		global $wpdb;

		// Ensures a row exists to update.
		add_post_meta( $product_id_with_stock, '_stock', 0, true );

		if ( 'set' === $operation ) {
			$new_stock = wc_stock_amount( $stock_quantity );

			// Generate SQL.
			$sql = $wpdb->prepare(
				"UPDATE {$wpdb->postmeta} SET meta_value = %f WHERE post_id = %d AND meta_key='_stock'",
				$new_stock,
				$product_id_with_stock
			);
		} else {
			$current_stock = wc_stock_amount(
				$wpdb->get_var(
					$wpdb->prepare(
						"SELECT meta_value FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key='_stock';",
						$product_id_with_stock
					)
				)
			);

			// Calculate new value for filter below. Set multiplier to subtract or add the meta_value.
			switch ( $operation ) {
				case 'increase':
					$new_stock = $current_stock + wc_stock_amount( $stock_quantity );
					$multiplier = 1;
					break;
				default:
					$new_stock = $current_stock - wc_stock_amount( $stock_quantity );
					$multiplier = -1;
					break;
			}

			// Generate SQL.
			$sql = $wpdb->prepare(
				"UPDATE {$wpdb->postmeta} SET meta_value = meta_value %+f WHERE post_id = %d AND meta_key='_stock'",
				wc_stock_amount( $stock_quantity ) * $multiplier, // This will either subtract or add depending on operation.
				$product_id_with_stock
			);
		}

		$sql = apply_filters( 'woocommerce_update_product_stock_query', $sql, $product_id_with_stock, $new_stock, $operation );

		$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.NotPrepared

		// Cache delete is required (not only) to set correct data for lookup table (which reads from cache).
		// Sometimes I wonder if it shouldn't be part of update_lookup_table.
		wp_cache_delete( $product_id_with_stock, 'post_meta' );

		$this->update_lookup_table( $product_id_with_stock, 'wc_product_meta_lookup' );

		/**
		 * Fire an action for this direct update so it can be detected by other code.
		 *
		 * @since 3.6
		 * @param int $product_id_with_stock Product ID that was updated directly.
		 */
		do_action( 'woocommerce_updated_product_stock', $product_id_with_stock );

		return $new_stock;
	}

Top ↑

Changelog Changelog

Changelog
Version Description
3.0.0 Introduced.


Top ↑

User Contributed Notes User Contributed Notes

You must log in before being able to contribute a note or feedback.